GeoLeaf Core API - v3.0.0
    Preparing search index...
    AttributeField: {
        [W in AttributeWidget]: AttributeFieldBase & {
            widget: W;
            primitive: AttributeWidgetPrimitive[W];
        } & (
            W extends "action"
                ? { options: AttributeWidgetOptions[W] }
                : { options?: AttributeWidgetOptions[W] }
        ) & (W extends AttributeDisplayOnlyWidget ? { edit?: undefined } : unknown)
    }[AttributeWidget]

    One field of a layer's attributes list.

    The union is built per widget so that primitive and options are both constrained by the chosen widget: declaring widget: "rating" with primitive: "string", or with a maxRows option, does not type-check.

    A descriptor carrying neither display nor edit is refused by the schema — a field that is neither read nor captured has no reason to be declared.

    ⚠️ A uses block of bindings to secondary subsystems lived here from 02/08 to 06/08/2026 and was REMOVED: it added a fourth list of field names without replacing any of the three that existed then (attributes.fields[], table.columns[], formSchema), and two of the five subsystems it bound to name no layer field at all. See A3‴ in roadmap_collecte-terrain-offline.md. formSchema itself went at task 7.2 — two lists remain.

    Two per-widget refinements ride on the conditional types below:

    • a display-only widget cannot carry edit;
    • action requires its options, because actionId is what identifies the button and a field without it renders nothing at all.