Theme
Customize the design system

Every control starts at the preset. Change one and every preview on the site follows, on this page and the next, until you reset it.

Contrast

Text against what it sits on. Below 4.5:1 fails WCAG AA for body text — the check a reviewer runs on any surface that takes a tone.

Waiting for the first preview to report its palette.

Corners

Sets all three radii at once. The individual values are under Geometry.

Brand 5

The accent seam an app actually brands itself through. Change these and you have made the decision a real `DesignTokens.graphite(...)` call makes.

Geometry 15

Square or rounded, and how heavy every line is. The radius row above the controls sets all three corners at once, because "what does square feel like" is one decision rather than three numbers.

Surfaces 17

Everything the app is painted ON — the ground behind the content (the frame paints it too), the cards over it, the well inset in a card, and the washes that show state.

Bands 10

The rail's head and the view bar beside it (one band across the top at 960 and wider), a pushed screen's bar, the compact bar and the compact nav bar — the band's fill, its rule, its hover and active faces, the resting field box on it, and the ink and accent control that sit on it. The rail's tree and its footer stay on the ground.

Text and controls 11

The ink ramp, the control outlines and the field's focus halo. Every pair the panel can break is watched by a contrast badge above.

Status 7

The three voices that mean something — danger, caution and ok — each as a foreground and a surface wash, danger with a border as well.

Data 5

The default pin head, its glyph and its halo, and the group bands. A pin's category color comes from the palette, named in the theme seed.

Map 11

The basemap's roles — land, water, parks, roads and their casings, buildings, labels — and the pending pin's gray. A raster basemap keeps its own imagery; these paint the map's plate and any kit-drawn map.

Scrollbars 6

Every scroller's bar: the thumb at rest and while hovered or dragged, the strip it rides, and the desk bar's thickness, side gap and corners. The desk half shows only while a fine pointer is attached; at touch the platform's own overlay keeps its size.

Advanced 6

Real controls that are not decisions — motion durations, the focus ring offset, the touch floor. Opens collapsed on purpose.

Take it with you

The Dart that reproduces what you are looking at. It is a real constructor call, because the configurator edits a real preset — what you copy is what an app can paste.

Screens

Records map

Reach for this for any spatial view — pins on a geographic basemap or on a fixed background image, one widget for both. The selected record docks as a detail pane rather than a bespoke summary panel. A verb on this screen has three homes and none of them is the bar: the primary one is the Fab (fab), view verbs like Export are the view-options surface's header affordance, and a record's own actions belong to the pushed record surface — see Detail's hosting knob.

Spec of record: design-system/components/data/MapView.d.ts

14
Knobs
5
Variants

Variants

Rendered scenarios from playground/scenarios.dart — the same registry the golden baselines gate on, so what you see here is what CI holds the widget to.

Zoom, attribution and the zero-pin empty state
map_view_states
Coincident pins merging into a count badge
map_view_clustered
Image mode over a floor plan
map_view_image_mode
Image mode over a PDF page
map_view_pdf_mode
The peek detent
pin_peek_card

Live

Real widgets, built from the real kit. Turn a knob and it rebuilds; the theme bar above applies the design system's own tokens — including anything you changed under Customize — and the device selector uses the same sizes the golden baselines gate on, so what you see here is what CI holds the widget to.

Press Focus on any preview to take it to the full window — at a desktop width that renders most devices at 1:1, which is when the widget's own controls become clickable. The bar always states the device and the scale, so a shrunk preview says it is shrunk. Esc leaves.

screen_records_map
Knobs
Theme

Marks within the radius merge into a count badge. The selected pin never clusters.

Collision distance in logical pixels.

Tap a pin. At 960 and wider the record docks as a side pane; below that it rises as a bottom deck.

Shows when you tap a pin — the pane is where the selected record docks — press Focus to make the preview interactive.

Assembly

Which nav the compact posture mounts — the drawer behind the hamburger, or a bottom bar.

The primary tier, and on a records destination the ONLY loud action the bar's neighborhood has. The scaffold renders it in the thumb zone at every window class; a screen never places it itself.

Actions in the drawer's own footer. The drawer carries them at EVERY window class — at 960 and wider it exists only because they do, since the expanded shell otherwise mounts a standing inline rail instead.

Shows when you open the drawer — the hamburger below 960, an edge swipe at 960 and wider, where the rail head's menu button toggles the rail instead. The actions sit in the drawer's own footer; the resting frame is identical either way. — press Focus to make the preview interactive.

The app's identity mark, and nothing else — it never opens a picker. At 960 and wider it sits beside the menu button in the rail's head at the same place in both postures, overhanging the collapsed rail so the bar beside it steps in. Below 960 the drawer's header band states it.

The scope — one value of the app's own kind (here an Area) — as the FIRST item of the bar's subtitle, ahead of the meta. With a picker it is a quiet text button with a chevron; on a phone the whole title block opens the picker as a bottom sheet. A pushed record's bar shows it read-only.

Global commands with no page ("Send feedback", "Help") pinned in the rail's footer under the footer destinations — the same row as a destination, but never lit and never counted in the destination index.

An organization's or partner's logo at the very bottom of the rail and the drawer — identity, never a control. Collapsed it shows its compact square, or nothing when the host gives none.

View

The Group and Columns panels beside the built-in Filter. `RecordsChrome.panels` is host-contributed and view-agnostic — the same cluster a table gets. OFF leaves Filter standing alone, which is a real posture: the tab row is absent at a single available control, because one control needs no tabs.

Shows when you open the view-options pane (tap Filter's control) — panels are TABS of that one pane, so the resting bar looks identical either way and only the pane's content differs — press Focus to make the preview interactive.

Dart for these values
screen_records_map()

What you can do in it

Capability the preview already carries that no knob can express — you reach it by using the widget. Worth knowing before concluding something is missing: most of this is only clickable once the preview is at Focus size.

The records chrome
  • **Search** — type in the field; the table narrows live. Collapsing search never clears the query, which survives as a removable search:… chip.
  • **Filter** — the funnel opens the view-options pane. Facets are type-appropriate: enums and text offer distinct values, numbers a min/max, dates a From/To.
  • **Chips** — every applied filter renders as a removable chip, and Clear all removes the lot.
  • **Narrowed to zero** states the narrowing and offers Clear, rather than the author-a-record empty state.
The records map
  • **Tap a pin** to select it; the record docks as a side pane at 960 and wider, and rises as a bottom deck below that.
  • **Drag the deck** between its two detents — peek shows the card, half shows the detail.
  • **Tap a cluster badge** to zoom to fit its members. Coincident pins never separate, by design.
  • **Tap the background** to deselect. Every transition reports through one channel.

What it is made of

The widgets this screen assembles, with their full API below. They used to live on a second entry of their own; one thing you choose gets one page.

AppMapView widget

The spatial record view — pins on a geographic basemap OR on a fixed background image, per `design-system/components/data/MapView.d.ts`: *"ONE widget, two modes… only the coordinate space differs."* The mode carries the coordinate space and viewport configuration; chrome, pins, pane, selection and…

Full dartdoc

The spatial record view — pins on a geographic basemap OR on a fixed background image, per `design-system/components/data/MapView.d.ts`: *"ONE widget, two modes… only the coordinate space differs."* The mode carries the coordinate space and viewport configuration; chrome, pins, pane, selection and placement are written once against it. The view owns the transient interaction state — which pin is selected and whether a create-placement is in progress — while the host owns the data consequences via onCreateAt, and owns the dataset itself (search, filter, result count) exactly as it does for `AppDataTable`. Pins are never edited or re-dragged on the map — the FORM owns position (`MapView.d.ts`); there is no move flow. **Selection** opens the detail pane (when detailPanelBuilder is set) and enlarges the tapped pin; every transition — tap, re-tap, background tap, pane dismiss — reports through onSelectPin, and a host holding selectedKey controls it outright. **Create** drops a reticle at the viewport center and reports the committed MapPoint via onCreateAt. **Camera, geo mode:** frames the pins exactly once, then stays put — if the first build already has pins it frames them immediately (empty → center on GeoMode.initialCenter; one → center on that pin; many → bounds-fit, padded); pins streaming in after an empty first build are framed once on the rebuild that first sees them. After that the camera is stable: selection, panning, and new pins never re-frame it. **Camera, image mode:** the pan/zoom viewport opens at the background's natural size and is kept stable across rebuilds by one transformation controller.

AppMapViewdefault constructor

Knob Type Default What it does
cluster bool true Collapses pins closer than clusterRadius px into a count badge (`MapView.d.ts`: default true). Distance-based — any two marks within the radius merge, so coincident pins can never half-bury each other — and the SELECTED pin never clusters. Tapping a badge zooms to fit its members.
clusterRadius double kDefaultClusterRadius The merge distance in screen px (the spec's default 46).
deckRest MapDeckRest
peek · header
MapDeckRest.peek The deck's FIRST rest (`MapView.d.ts` THE DECK MAY REST AT THE RECORD'S HEADER, #1018): MapDeckRest.peek, the default, opens the deck at the small PEEK carrying peekBuilder's card. MapDeckRest.header opens it at the MEASURED height of the detailPanelBuilder body's header — an `AppDetailView` reports…
detailPanelBuilder Widget Function(BuildContext context, String rowId)? null Builds the detail pane body for a selected row id. Null disables the pane; a pin tap then selects only for a host that listens through onSelectPin (a records map body docking its record in the floorplan's own pane, `MapView.d.ts` THE MAP'S RECORD IS THE RECORDS PANE), and otherwise only fires…
detailPosture MapDetailPosture
auto · side · deck
MapDetailPosture.auto Where the record pane stands (the spec's `detailPosture`): MapDetailPosture.auto, the default, docks it at the side at the expanded window class and decks it below; `side` / `deck` force one. The visible rect every fit and the selection nudge target follows the posture that renders.
emptyActionLabel String? null Empty-state action label (renders only with onEmptyAction).
emptyActionNavigates bool false THE ACTION THAT ONLY OPENS A PAGE (`ActionStrip.d.ts`, #1749): the empty face's action pushes another screen and writes nothing, so it reports a link to assistive technology. Declared, never inferred from onEmptyAction. Default false.
emptyLabel String? null Zero-pin empty-state title. Null renders no empty overlay (the bare surface is the empty face). With a label, the designed composition renders centered: the label plus at most one action.
formatRules List<FormatRule<T>>? null THE LOCATION COLUMN'S FORMAT RULES (`FormatRules.d.ts`, #977; `MapView.d.ts` ONE CHANNEL PER JOB, #972): the first holding rule's `color` is a pin's FILL (its category) and its `glyph` the head's glyph; `paint` and the text treatments do not reach a mark. The rule's row is the pin's MapPin.row and…
frameEpoch int 0 Programmatic fit-all (the spec's `frameEpoch`): whenever this value CHANGES on a mounted view the camera re-frames to fit the currently visible pins — the control stack's fit-all, host-triggered. The host bumps it when its surface re-enters the foreground (a records destination being revisited), so…
fullscreen bool? null Controlled fullscreen state — whether the host is showing the map full screen, which the toggle's glyph and title state. Null reads as not full screen. The HOST owns what fullscreen means (route, overlay); the view only reports the request.
gestureHandling MapGestureHandling
direct · cooperative
MapGestureHandling.direct Who owns a one-finger drag and a plain wheel (the spec's `gestureHandling`, COOPERATIVE GESTURES): MapGestureHandling.direct — the default — the map; MapGestureHandling.cooperative the enclosing scroller. A host chooses cooperative only where an enclosing scroller competes for the drag — the…
initialSelectedRowId String? null Row id selected on first build, or null. Silently a no-op highlight-wise if no pin matches — the detail pane still opens for the id (e.g. a not-yet-synced deep link).
layers MapLayers? null THE LAYERS CONTROL (`MapView.d.ts` `layers`, THE MAP'S FLOATS ARE SMALL CARDS, #894): the host's named basemaps and, since A DRAWING IS A LAYER (#1084), its drawings — the one up now and the choice. Two or more options render the Layers group, LAST in the control stack, in EITHER mode — an anchored…
legend List<MapLegendGroup>? null THE PIN LEGEND (`MapView.d.ts` THE LEGEND DECODES THE PINS, #593): the key to the pin encoding, one group per channel, drawn on one plate at the visible rect's bottom-start. It opens OPEN except at the compact window class, where it opens closed to its one button, and the user shows and hides it…
legendOpen bool? null THE LEGEND'S OPEN STATE MAY BE THE HOST'S (`MapView.d.ts`, #1058): set (true or false), the legend's state on every build — its show and hide controls report the state they ask for through onLegendOpenChanged and change nothing themselves, so a remount renders the host's value at once. Null, the…
loading bool false THE MAP MAY STATE ITS LOAD (`MapView.d.ts`, #1085): true lays ONE pulsing skeleton plate over the whole surface, inert and announced as loading. It outranks the empty face, and the meta, the legend, the control stack, the scale, the attribution and the add Fab stand down; whatever pins holds lies…
meta String? null The quiet top-start annotation (the spec's `meta`): a SENTENCE in the UI font on a float card, each figure at 600 in ink ("14 pins", THE MAP'S FLOATS ARE SMALL CARDS, #894). Null or empty renders none.
mode * MapMode — The coordinate space + viewport configuration — GeoMode or ImageMode.
onBoundsChange void Function(MapViewBounds bounds, double zoom, {required bool userGesture})? null THE VIEWPORT REPORT, MODE-NEUTRAL (`MapView.d.ts`, 2026-09-27): every camera move reported as the VISIBLE RECT plus zoom — the spec's widened `onViewChange` payload and a dashboard harness's viewport scope — in the coordinate space of mode: GeoViewBounds (lat/lng, the flutter_map zoom) under…
onCreateAt void Function(MapPoint point)? null Invoked when a create-placement is committed, with the viewport-center coordinate. Null disables the create affordance.
onEmptyAction VoidCallback? null Empty-state action callback (renders only with emptyActionLabel).
onFullscreenChange ValueChanged<bool>? null The host's report of the fullscreen toggle, and its PRESENCE renders the toggle (`MapView.d.ts` THE CONTROL STACK IS ONE ANSWER: full screen is the host's to offer, because only a host knows what it covers). Null renders no toggle — a dashboard map tile, whose focus toggle is its one way to enlarge.
onLegendOpenChanged ValueChanged<bool>? null Reports the state the reader's show or hide press asks for, whether or not legendOpen is set — never a legendOpen change, the mount, or the legend standing down while the deck is up or while placing (which is not a close: the legend returns in the state it had).
onLegendToggle void Function(String group, String entry)? null Makes every legend entry a TOGGLE: a tap reports `(group, entry)` and the HOST narrows its own dataset, then hands back the pins that survive and each entry's MapLegendEntry.shown. The view owns no visibility state of its own — on a records map the toggle IS the Filter tab's facet (one narrowing, so…
onOpenRecord void Function(String rowId)? null Escalates the open pane's record (its id) to the host's full-screen detail surface. Non-null renders the expand/maximize affordance in the pane's ONE chrome row, leading the ✕ — the top-corner surface affordance `DetailView.d.ts` specifies, never a button on the record's own action row. Null omits…
onPinTap void Function(T row)? null Invoked with the tapped pin's typed row.
onPlacingChange ValueChanged<bool>? null Observes every placing transition the view initiates — begin (FAB), commit, cancel, and a pin tap abandoning the flow. The controlled half's `onChanged`; also fired in uncontrolled mode so a host can mirror the state without owning it.
onSelectPin void Function(String? key, T? row)? null Reports EVERY selection transition (the spec's `onSelectPin(key|null)`) — a pin tap (its key + typed row), a re-tap, a background tap, and the pane's dismiss (all null, null). The one observation channel; without it a host cannot know the pane closed. Its PRESENCE makes a pin tap select and mark the…
onViewChange void Function(MapPoint center)? null Fires on every viewport change with the coordinate under the reticle — a narrowed binding of the spec's `onViewChange` (`{center, zoom}`): center only, because no consumer reads zoom yet; widen it additively when one does. The picker pattern's live readout consumes it.
peekBuilder Widget Function(BuildContext context, String rowId)? null Builds the deck's PEEK content for a selected row (`MapView.d.ts` PeekCard) — `PinPeekCard` with the identifying facts. Non-null gives the compact deck its PEEK rest height: it opens at `--map-deck-peek` showing the card's header row, and swaps to detailPanelBuilder's body on the way up to…
pins * List<MapPin<T>> — Pins to plot. Every pin's MapPin.point variant must agree with mode; the view asserts this in debug builds.
placeGlyph KitIconRef KitGlyph.plus The glyph the placement reticle's head carries (`MapView.d.ts` `placeIcon`, #961) — KitGlyph.plus by default. A host whose new record is a typed mark (a hazard, a hydrant) names that mark's glyph, so the reticle previews the pin the commit will draw.
placing bool? null Controlled placing mode (the spec's `placing` — "the host can also enter it from a toolbar"). Null keeps placing uncontrolled (the internal FAB flow). `true` shows the reticle; with onCreateAt set the confirm/cancel bar renders and CAN COMMIT (the controlled flow is a full flow, not a dead end);…
selectedKey String? null Controlled selection (the spec's `selectedKey`). While non-null-aware hosts keep using initialSelectedRowId, a host that passes this owns the selection outright: a change (including to null) adopts, and every internal transition still reports through onSelectPin so the host's copy never drifts.
showZoom bool? null Renders the ± pair in the control stack (`MapView.d.ts` THE CONTROL STACK IS ONE ANSWER, 2026-09-27). Null — the default — FOLLOWS THE POINTER: shown while a fine pointer is attached (AppPointerPosture.desk, where a wheel zooms but nothing pinches), hidden on a touch-only surface, where pinch is…

PinPeekCard widget

Blessed compact content for a pin surface's detail panel. A status dot + title header, then a short label/value list of the record's key fields.

Full dartdoc

Blessed compact content for a pin surface's detail panel. A status dot + title header, then a short label/value list of the record's key fields. The deck's PEEK (MapViewTheme.sheetPeekHeight, the spec's `--map-deck-peek`, 96) shows the HEADER ROW — the dot, the title line and the Open affordance — with the facts below the fold, one drag away (THE DECK PEEKS SMALL AND DRAGS FREE, #831). Hosts pass a builder returning this to `PinSurfaceScaffold` / `MapSurface` / `DrawingSurface`'s `detailPanelBuilder`; the full record is reachable via onExpand (or the host's own expanded layout once the sheet is dragged open). The deck's PEEK detent RELIES on onExpand: it draws no `expand / close` control row, so at peek this card carries the only escalate affordance. Keep fields short — this is a peek, not the record. Paints from DesignTokens like the rest of the map anatomy. Fields are the detail view's own AppDetailField (D-01 / the spec's `PeekCardProps` — `fields` are DetailView fields), rendered in the label-rail form (detailFieldValue + detailUsesLabelOver) rather than the kit definition list, because a peek panel is width-constrained where a detail view is not.

PinPeekCarddefault constructor

Knob Type Default What it does
fields List<AppDetailField<T>> const [] The short label/value list rendered below the header. Keep this to the record's key fields — a peek, not the full detail view.
onExpand VoidCallback? null Invoked by the trailing chevron affordance that opens the full record. Null hides the affordance.
row * T — The row every field extractor in fields reads from.
statusColor Color? null Mirrors the pin's marker color. Null hides the leading status dot.
title * String — The header line — the record's primary label. Ellipsizes to a single line rather than wrapping, so the header row the peek shows never grows past its budget.

MapTileScope widget

Provides a MapTileConfig to descendants (e.g. the location picker). Mirrors `LocationCaptureScope` — the app installs it once at the composition root.

MapTileScopedefault constructor

Knob Type Default What it does
child * dynamic —
config * MapTileConfig — The basemap tile source.

LatLongPicker widget

A map screen for picking a lat/long — the picker pattern over AppMapView (one-map-view spec, phase 2). This surface IS the map view's pin-dropper, hosted as a route: the same bobbing reticle, the same ✓ confirm / ✕ cancel placement bar, the same snap-to-me control in the viewport stack — so placing…

Full dartdoc

A map screen for picking a lat/long — the picker pattern over AppMapView (one-map-view spec, phase 2). This surface IS the map view's pin-dropper, hosted as a route: the same bobbing reticle, the same ✓ confirm / ✕ cancel placement bar, the same snap-to-me control in the viewport stack — so placing a point reads identically whether the user is on the records map or inside a form. The pattern owns only what the component deliberately does not: which tile template renders (the satellite/street choice, read off MapTileScope and offered through the control stack's LAYERS group), the GPS fix behind the locate control, and where the committed point goes (the route's result). The live coordinate rides the component's own meta float rather than bespoke overlay chrome — and so does the picker's TRANSIENT LINE: a refused "use my location" (a denied permission, services off, no fix in time) shows its sentence there for the modeline linger and moves nothing (#793). With no LocationCaptureScope the locate control is ABSENT, never broken. The web twin is `web/packages/ui/src/patterns/LatLongPickerView.tsx`. THE EMPTY FIELD'S OPENING CAMERA (CaptureField.d.ts, #1373). With no initial value the picker opens on fallbackCenter, else on the WORLD VIEW (`_worldZoom` over (0, 0)) — never region zoom over open ocean — and, with a LocationCaptureScope, runs ONE locate on open. A fix moves the still-untouched camera to the device at _pickerZoom, through the map view's async-arrival move (a changed `GeoMode.initialCenter`, M-02), which already stands down once the user has moved. A refusal, a null fix or a throw is SILENT — it is not a press — and the camera stays where it opened. Until the user's first move the meta chip carries the cue (`FormVocabulary.latLongLocating`, `latLongNoLocation`) instead of a bare (0, 0).

LatLongPickerdefault constructor

Knob Type Default What it does
fallbackCenter CaptureLocationCenter? null The host's place to open an EMPTY field on (`FormView.d.ts` `CaptureLocationPicker.fallbackCenter`) — a project's centroid, a site's address — at its own zoom, else _pickerZoom. Read only when initial is null; shown while the opening locate is pending, refused or unavailable. Null opens an empty…
initial * LatLng? — Initial camera center (existing value), or null for an EMPTY field, which opens on fallbackCenter or the world view and locates once.
tileProvider TileProvider? null Explicit tile provider, overriding everything below it. Widget tests pass a stub here so they never hit the network. When null, AppMapView resolves tiles through the ambient `MediaCacheScope` if one is installed, and otherwise flutter_map's default network-only provider.

ImagePointPicker widget

A full-screen surface for placing a point on a drawing — the picker pattern over AppMapView in IMAGE mode, the image-space twin of `LatLongPicker`. The SAME placement grammar as the location picker: the map view's own create-flow posture — the bobbing reticle over the viewport center, the placement…

Full dartdoc

A full-screen surface for placing a point on a drawing — the picker pattern over AppMapView in IMAGE mode, the image-space twin of `LatLongPicker`. The SAME placement grammar as the location picker: the map view's own create-flow posture — the bobbing reticle over the viewport center, the placement bar's ✓ confirm / ✕ cancel — hosted as a route, so placing a point reads identically on a records map, a location field and here. The pattern owns only what the component does not: the route chrome (Cancel and `FormVocabulary.xyPickerTitle`), where the camera opens (on initial at the one-pin scale through `ImageMode.initialCenter`, else the whole drawing), the live readout in the meta float (imagePointLabel), and THE MANUAL ROW below the map — a quiet toggle revealing `X %` / `Y %` and a Done that commits the typed pair, clamped into `0..100`, for a position the reader already knows. The web twin is `web/packages/ui/src/patterns/ImagePointPickerView.tsx`.

ImagePointPickerdefault constructor

Knob Type Default What it does
drawing * ImageMode — The drawing the point is placed on.
initial ImagePoint? null The stored point the camera opens on, or null to open on the whole drawing.

Types its knobs take

These are not things you choose — they are the shapes the knobs above expect. They live under this entry rather than in the navigation for exactly that reason.

AppDetailField support

One typed field in an AppDetailSectionKind.fields section — a definition-list entry over the record type T. A field is pure typed metadata: a label (the definition term, on the label rail), a type deciding the value grammar (shared with the table — an ID chip, a data-font number, a status word…),…

Field Type Default What it does
danger bool Function(T record)? null Per-record danger predicate — when it returns true the value paints DesignTokens.danger AND takes em weight, in **every** grammar (an overdue date, a blocked status, a negative balance), not only on enums. Danger only where action is demanded; null never paints the value danger.
emptyLabel String? null The word rendered in place of the em-dash when this field's value is empty ('Unassigned', 'No date'). Null (the default) renders the em-dash mark. Either way the field renders — an empty value never disappears unless its section hides empty fields (AppDetailSection.hideEmpty).
formatRules List<FormatRule<T>>? null FORMAT RULES (`DetailView.d.ts` `DetailField.formatRules`, `FormatRules.d.ts`, #977) — the SAME list the record's table column declares (`AppColumn.formatRules`), so one value reads one way in a row and in a detail. The field's value is the subject; `of` reads the record the view shows. Reaches the…
formatRulesOf FormatRulesOf<Object?>? null THROUGH A REFERENCE (`DetailView.d.ts` `DetailField.formatRulesOf`, `FormatRules.d.ts`, #1032): a field that shows a reference wears the REFERENCED row's rules. `resolve` is handed the field's value and the record the view shows, and the target row is the rules' row. Walked after formatRules, only…
label * String — The definition term — rendered on the label rail in DesignTokens.label (micro-label), the `<dt>` of the definition list.
locationLabel String? Function(T record)? null AppCellType.latLong only: the place the host resolved for this record's point ("North gate, Pad 4"), drawn beside the pin IN PLACE OF the coordinates (`DetailView.d.ts` A LOCATION READS AS A PLACE, #929). The coordinates stay the tooltip and join the accessible name, and the copy button still copies…
locationPreview bool false AppCellType.latLong only: draw a still map of the point UNDER the readout (`DetailView.d.ts` A LOCATION FIELD MAY SHOW ITS MAP, #1281) — the point centered at the map's one-pin zoom with one pin, on the ambient MapTileScope's satellite raster, else the graticule plate. It is for a detail that reads…
measure AppDetailMeasure? null How this field's value wraps (`DetailView.d.ts` LONG TEXT FILLS ITS BOX, #909). Null takes the section's AppDetailSection.measure, else AppDetailMeasure.fill — the value wraps at its field box and keeps its own line breaks. AppDetailMeasure.reading caps it at 65ch of the body role, never wider than…
numberFormat AppNumberFormat? null How an AppCellType.number or AppCellType.percent value reads — `DataTable.d.ts` NumberFormat, UNCHANGED and through the table's own formatter (appCellContent), because a value does not change meaning by moving from a row to a detail. Declare the same format the column showing this datum declares.…
onEdit VoidCallback? null Per-field quick-edit callback. When set the row shows a trailing quiet edit affordance (a ghost pencil AppIconButton) and firing it invokes this. Null (the default) renders a read-only row with no affordance.
onNavigate void Function(T record)? null Navigation handler for an AppCellType.link field — the value renders accent-painted with a trailing chevron on a ≥DesignTokens.touch target, and firing it invokes this with the record. Null renders the inert link form (the reference still SHOWS; it just does not pretend to navigate). Unlike onEdit…
options List<FieldOption>? null AN OPTION'S LABEL READS IN THE DETAIL (`DetailView.d.ts` `DetailField.options`, 2026-10-20, #1635): the SAME list the field's form editor and its table column take (`AppColumn.options`), so one datum prints one string on the form, the cell and the detail. Read by AppCellType.enumValue,…
refLabel String? Function(String id)? null AppCellType.ref / AppCellType.refList: a stored key's label (`DetailView.d.ts` `DetailField.refLabel`, EVERY FORM TYPE HAS A READ FACE, #1645) — the same resolver the field's form editor and its table column read (`AppColumn.refLabel`). A null or blank answer leaves the key UNRESOLVED: the key…
render Widget Function(T record)? null Full custom value builder — the escape hatch mirroring `AppColumn.render`. When non-null it wins over type, emptyLabel and the empty mark entirely: the caller owns the whole value widget. Use sparingly; the canonical grammars (type) cover the common cases, and a bespoke value in a definition list is…
span int 1 Column span in the field grid — 1 (the default), 2 (two tracks), or spanFull (the whole row at every track count). Clamped to the live track count, so a span never overflows the grid; ignored by the inline layouts, whose value already fills the row.
status AppStatusMarkTone? Function(T record)? null STATUS (`DetailView.d.ts` `DetailField.status`, Contained, 2026-09-29, #893) — the value is a stored status, rendered as the STATUS MARK (AppStatusMark) in the tone this returns for the record: the word with its marker, or the filled danger tag for AppStatusMarkTone.blocked. It WINS over danger —…
tier AppDetailFieldTier AppDetailFieldTier.primary A FIELD MAY STEP ASIDE BY ITS TIER (`DetailView.d.ts` `DetailField.tier`, 2026-10-24, #1805). AppDetailFieldTier.primary (the default) renders as before; AppDetailFieldTier.secondary is hidden behind its section's note row until the reader shows it, then in its authored place. It needs no…
type AppCellType AppCellType.text How the value renders — the shared AppCellType grammar. Defaults to AppCellType.text. Ignored when render is supplied.
unitOf AppNumberUnit? Function(T record)? null THE ROW'S OWN UNIT (`DetailView.d.ts` `DetailField.unitOf`, #884) — the same accessor the record's column declares (`AppColumn.unitOf`), read against the record the view shows. A present result replaces numberFormat's unit; null or blank leaves it standing; with no numberFormat the unit trails the…
units List<QuantityUnit>? null AppCellType.quantity: the unit choices (`FieldSpec.units`, `DetailView.d.ts` `DetailField.units`, #1645), read for each code's label (`150 psig`). Ignored by every other type. Null: a unit reads as its code.
value * Object? Function(T record) — Typed value accessor — reads this field's value from a record. Its return type pairs with type (a `String` for id/text/enumValue/person, a `num` for number/progress, a `String`/`DateTime` for date, an `ImageProvider?` for image). A closure over the typed record — never a map lookup.

CaptureLocationCenter support

The host's FALLBACK CENTER for an empty location field — `FormView.d.ts`'s `CaptureLocationCenter` (CaptureField.d.ts THE EMPTY FIELD'S OPENING CAMERA, steady-core #1373): where the full-screen picker opens when the field has no value, while its opening locate is pending, refused or unavailable. A…

Field Type Default What it does
center * LatLng — The point to open on.
zoom double? null The zoom to open at; null takes the picker's region zoom (13).

FormatRule support

One FORMAT RULE (`FormatRules.d.ts` THE FORMAT RULE): a match and its effects. A rule list is ORDERED and the FIRST holding rule formats the value; a rule with no match always holds, so written last it is the column's default.

Field Type Default What it does
color KitColor? null A palette name or a color parsed from data — on a map pin, its FILL.
em bool false The word at the em weight.
glyph KitIconRef? null A glyph — on a map pin, the head's glyph.
italic bool false The word italic.
label String? null What the rule means, in the host's words — read by a legend, a chip and the accessible name.
match FormatMatch<T>? null The predicate, or null for "always holds" (the default rule).
muted bool false The word at ink40 (ignored under FormatPaint.ink and FormatPaint.tag).
paint FormatPaint FormatPaint.mark How color lands on a value (FormatPaint.mark by default).
strike bool false The word struck through, in its own ink.

ImageMode support

Fixed-background mode — pins live in normalized image space. The spec names its use cases directly: engineering drawings, site plans, floor plans.

Field Type Default What it does
background * ImageProvider? — The raster drawing the pins are placed on — null under ImageMode.pdf. Any ImageProvider; the view resolves its natural size before the first pin renders, because normalized coordinates cannot be projected without it.
initialCenter ImagePoint? null Where a map with NO PINS opens — `MapView.d.ts` `defaultCenter` under image mode (AN IMAGE MAP MAY OPEN ON A POINT, 2026-10-08): the camera centered on this point at the one-pin scale (twice the contain fit, the scale a lone pin mounts at) instead of the whole drawing. With pins the pins frame as…
semanticLabel String? null Accessible name for the background (the spec's `alt`). Null renders without a semantics label.
Field Type Default What it does
fallback ImageProvider? null THE PDF IS PREFERRED (`MapView.d.ts`, 2026-10-09): under ImageMode.pdf, a raster of the same sheet — the fallback the view draws when the page cannot be read (corrupt, password-protected, an engine that fails). The page is the better source: it re-rasterizes sharp at every zoom, and markup needs its…
initialCenter ImagePoint? null Where a map with NO PINS opens — `MapView.d.ts` `defaultCenter` under image mode (AN IMAGE MAP MAY OPEN ON A POINT, 2026-10-08): the camera centered on this point at the one-pin scale (twice the contain fit, the scale a lone pin mounts at) instead of the whole drawing. With pins the pins frame as…
markup MarkupBinding? null MARKUP OVER A DRAWING (`MapView.d.ts`, 2026-10-09; `Markup.d.ts`): real PDF annotations over the ImageMode.pdf page, in the page's own space inside the map's zoom. Drawn only while the view draws the page from the PDF (never over fallback); the map offers no rotation, so the binding's `onRotate` is…
page int 0
renderer PdfPageRenderer? null
semanticLabel String? null Accessible name for the background (the spec's `alt`). Null renders without a semantics label.
source * PdfPageSource —
space PdfPointSpace PdfPointSpace.drawn A DRAWING'S POINTS MAY BE THE PAGE'S (`MapView.d.ts`, 2026-10-20): the space every point about an ImageMode.pdf drawing is stated in — each pin's, initialCenter, the placed point and the bounds report. PdfPointSpace.page is the page's unrotated crop box, and the view applies the file's `/Rotate`;…

ImagePoint support

An image-relative coordinate (MapMode `image`), both axes normalized to `[0, 1]` per the spec — `(0, 0)` is the background's top-left, `(1, 1)` its bottom-right. Normalized 0-1, NOT the percent `[0, 100]` the deleted `DrawingPoint` carried: the spec says 0-1, nothing consumed the percent shape, and…

Field Type Default What it does
x * double — Horizontal position, `0` = left edge, `1` = right edge.
y * double — Vertical position, `0` = top edge, `1` = bottom edge.

KitIconRef support

A glyph, by NAME — what every glyph-bearing kit API takes (a pin, a legend key, a nav item, an action, an empty face, a category card). Two shapes implement it: - a KitGlyph — a glyph in the kit's own name table, checked by the compiler (`KitGlyph.syringe`); - KitIconRef.named — any name as a…

Field Type Default What it does
name * String —

MapLayers support

THE LAYERS CONTROL's channel (`MapView.d.ts` `MapLayers`, THE MAP'S FLOATS ARE SMALL CARDS, Contained, #894; A DRAWING IS A LAYER, #1084): the host's named basemaps and drawings, the one up now, and the choice. Two or more options render the Layers group, LAST in the control stack; fewer render…

Field Type Default What it does
current * String — The key of the layer up now — the menu's check.
onChange * ValueChanged<String> — Reports the chosen option's key. The host swaps its channel.
options * List<MapLayerOption> — The choices, in menu order. Fewer than two: no Layers group.

MapLegendGroup support

One group of an `AppMapView`'s pin legend — one channel of the encoding (a category color, a type glyph, a status), laid as ONE ROW of keys after its optional title.

Field Type Default What it does
entries * List<MapLegendEntry> — The keys, in the order the host gives them.
key * String — The group's identity — reported back through `AppMapView.onLegendToggle`. On a records map it is the facet column's key.
mark MapLegendMark MapLegendMark.head How the group's keys are drawn — pin heads, or status badges.
title String? null The group's title — the row's first word, in the label role — or null for none.

MapMode support

The coordinate space and viewport configuration of an `AppMapView`. Sealed: `geo` (a web-mercator tile basemap) and `image` (a fixed background drawing) are the spec's two modes.

MapPin support

A single placed pin on an AppMapView — the typed row plus its resolved presentation. The host maps each domain row to a MapPin once (parse its coordinate, state its tone, name it via label, and its own color / glyph when the record states them) and hands the list to the view; the view never touches…

Field Type Default What it does
color KitColor? null The pin's CATEGORY — the head's FILL: a palette name (KitColor.named: a built-in hue or a host category declared in the theme seed) or a color parsed from data (KitColor.parse). Wins over `AppMapView.formatRules`; null with no rule color leaves the fill to the tone, else DesignTokens.pinFill…
glyph KitIconRef? null The glyph the pin head carries — the TYPE. Null takes the holding format rule's glyph, else KitGlyph.dot, the neutral mark.
id * String — Stable row id — the selection key. Kept separate from row so the view never assumes the opaque `T` exposes an id.
label String? null The pin's tooltip / accessible name (the spec's `labelField`). Null renders no semantics label.
point * MapPoint — The pin tip's position, in the coordinate space of the hosting view's MapMode — a GeoPoint under GeoMode, an ImagePoint under ImageMode. The view asserts the two agree in debug builds.
provisional bool false Default false. True draws THE PROVISIONAL MARK (`MapView.d.ts`, 2026-10-20): a placement nobody has confirmed, hollow and dashed. Not tone `pending`, which is the RECORD's status; this is the PLACEMENT's.
row * T — The typed domain row this pin represents; returned to the host on tap.
tone AppStatusMarkTone? null The pin's STATUS (`MapView.d.ts` ONE CHANNEL PER JOB, #972) — `pending`, `active`, `done` or `blocked`. On a pin with a category (color, or its format rule's) it rides the STATUS BADGE; on one with none it fills the head (`pending` → DesignTokens.pinPending, `active` → the accent, `done` → ok,…

MapPoint support

A coordinate in one of the map's two spaces. Sealed so a `switch` over it is exhaustive — the compiler catches a mode that forgets a capability.

MapTileConfig support

Provider-agnostic basemap tile source. The app supplies concrete URL templates (with any API key already substituted) so the foundation never hardcodes a provider or secret.

Field Type Default What it does
attribution * String — Attribution string rendered on the map (required by MapTiler/OSM ToS).
satelliteUrlTemplate * String — `{z}/{x}/{y}` satellite tile URL template (key already embedded).
streetUrlTemplate * String — `{z}/{x}/{y}` street tile URL template (key already embedded).
userAgentPackageName String 'unknown' The consuming app's package identifier, sent in the `User-Agent` of every tile request. Tile providers' usage policies (OSM's in particular) require an identifying agent, and only the app knows its own id — the foundation must never carry one. Defaults to `flutter_map`'s own placeholder so a config…

MapViewBounds support

The visible rect an `AppMapView` reports through its mode-neutral `onBoundsChange` (`MapView.d.ts` THE VIEWPORT REPORT IS MODE-NEUTRAL) — in the coordinate space of the view's MapMode. Sealed so a host switches exhaustively: GeoViewBounds under GeoMode, ImageViewBounds under ImageMode.

Where it lives

Class File
AppMapView packages/app_widgets/lib/src/kit/data/map_view.dart
PinPeekCard packages/app_widgets/lib/src/kit/data/pin_peek_card.dart
MapTileScope packages/app_widgets/lib/src/kit/data/map_tile_scope.dart
LatLongPicker packages/app_widgets/lib/src/patterns/lat_long_picker_view.dart
ImagePointPicker packages/app_widgets/lib/src/patterns/image_point_picker_view.dart