{
  "version": 1.1,
  "tags": [
    {
      "name": "om-map",
      "description": "The map root. Layers, overlays, behaviors, widgets, and stories are children.",
      "attributes": [
        {
          "name": "center",
          "description": "Initial center \"[lng, lat]\"."
        },
        {
          "name": "zoom",
          "description": "Initial zoom."
        },
        {
          "name": "pitch",
          "description": "Initial pitch in degrees."
        },
        {
          "name": "bearing",
          "description": "Initial bearing in degrees."
        },
        {
          "name": "basemap",
          "description": "Basemap: a registered preset name, \"maplibre\" (demo style), a style URL, or \"none\" (standalone canvas).",
          "values": [
            {
              "name": "maplibre"
            },
            {
              "name": "none"
            },
            {
              "name": "liberty"
            },
            {
              "name": "bright"
            },
            {
              "name": "positron"
            },
            {
              "name": "dark-matter"
            },
            {
              "name": "voyager"
            },
            {
              "name": "osm"
            },
            {
              "name": "maptiler-streets"
            },
            {
              "name": "maptiler-dataviz"
            },
            {
              "name": "maptiler-satellite"
            }
          ]
        },
        {
          "name": "basemap-key",
          "description": "Provider API key for keyed basemap presets (maptiler-*) — publishable origin-restricted key; or call OmMap.configureBasemap once."
        },
        {
          "name": "attribution",
          "description": "Set \"false\" to opt out of the compact attribution control shown with basemaps.",
          "values": [
            {
              "name": "false"
            }
          ]
        },
        {
          "name": "lighting",
          "description": "Scene lighting preset for 3D content — seeds ambient/sun/camera values that lighting-* attributes override. Absent = deck.gl default lights.",
          "values": [
            {
              "name": "daylight"
            },
            {
              "name": "studio"
            },
            {
              "name": "flat"
            },
            {
              "name": "custom"
            }
          ]
        },
        {
          "name": "lighting-ambient",
          "description": "Ambient light intensity (always-on fill), e.g. 0.9."
        },
        {
          "name": "lighting-sun",
          "description": "Sun (directional light) intensity; 0 removes the sun."
        },
        {
          "name": "lighting-sun-azimuth",
          "description": "Sun compass bearing, degrees clockwise from north [0, 360)."
        },
        {
          "name": "lighting-sun-elevation",
          "description": "Sun height above the horizon, degrees [0, 90]."
        },
        {
          "name": "lighting-sun-date",
          "description": "ISO 8601 or epoch ms — computes the sun's azimuth/elevation from solar position at the map center (shadow studies). Overrides azimuth/elevation."
        },
        {
          "name": "lighting-camera",
          "description": "Camera-following fill light intensity (model inspection); 0 removes it."
        },
        {
          "name": "terrain",
          "description": "3D elevation surface: a registered terrain preset, a {z}/{x}/{y} DEM URL (needs terrain-decoder), or \"off\". Replaces an active basemap while on. Geographic layers drape by default (per-layer terrain attribute overrides).",
          "values": [
            {
              "name": "off"
            },
            {
              "name": "terrarium"
            },
            {
              "name": "maptiler-terrain"
            },
            {
              "name": "mapterhorn"
            }
          ]
        },
        {
          "name": "terrain-decoder",
          "description": "DEM RGB decoder: \"terrarium\", \"mapbox-rgb\", or {rScaler,gScaler,bScaler,offset} JSON. Required for raw DEM URLs; presets carry their own.",
          "values": [
            {
              "name": "terrarium"
            },
            {
              "name": "mapbox-rgb"
            }
          ]
        },
        {
          "name": "terrain-exaggeration",
          "description": "Vertical relief multiplier, applied in the DEM decoder; 1 = true relief."
        },
        {
          "name": "terrain-max-zoom",
          "description": "DEM tileset zoom cap — the provider's REAL limit (a too-high cap requests 404 tiles and blanks the terrain)."
        },
        {
          "name": "terrain-texture",
          "description": "Optional {z}/{x}/{y} imagery template draped over the surface (satellite, etc.)."
        },
        {
          "name": "clip-box-min",
          "description": "3D clip box corner \"[lng, lat, elevation]\" — with clip-box-max, cuts every layer (opt out per-layer with clip=\"off\") down to what's inside the box. Axis-aligned."
        },
        {
          "name": "clip-box-max",
          "description": "3D clip box opposite corner \"[lng, lat, elevation]\" — see clip-box-min."
        },
        {
          "name": "clip-box-invert",
          "description": "Show what's OUTSIDE the clip box instead of inside."
        },
        {
          "name": "clip-box-highlight",
          "description": "Dim clipped-out geometry instead of discarding it (non-destructive preview) — nothing disappears, it just de-emphasizes."
        },
        {
          "name": "snap",
          "description": "XY snapping for draw/measure vertex capture: space-separated agents (vertex, edge, midpoint). Refines deck's own hover/click pick to the nearest vertex/edge/midpoint of the ALREADY-picked feature within snap-tolerance pixels — searches every pickable vector layer's geometry by default, opt a layer out with snap=\"off\". Hold Space to suppress momentarily.",
          "values": [
            {
              "name": "vertex edge midpoint"
            },
            {
              "name": "vertex"
            },
            {
              "name": "edge"
            },
            {
              "name": "midpoint"
            }
          ]
        },
        {
          "name": "snap-tolerance",
          "description": "Snap search radius in screen pixels (default 12)."
        },
        {
          "name": "widget-style",
          "description": "Layout-token sugar: space-separated key:number pairs → --om-widget-* custom properties (e.g. \"gap:10 opacity:0.9\"). Keys: inset, gap (shorthands), inset-x/-y, gap-x/-y, opacity, radius, size. Numbers are px except opacity."
        },
        {
          "name": "widgets-hidden",
          "description": "Hide-all: every widget goes visibility:hidden (state survives — no removal) except attribution and widgets-toggle, which never hide. Toggle via the set-widgets-visible action or <om-widget type=\"widgets-toggle\">; transient UI, not an undo step; story-scrub-capturable."
        },
        {
          "name": "widgets-fold",
          "description": "Responsive auto-fold is on by default at map widths ≤ --om-widget-fold-breakpoint (640px): managed widgets move into one accessible drawer per map side. Set \"off\" to disable.",
          "values": [
            {
              "name": "off"
            }
          ]
        },
        {
          "name": "widgets-dim",
          "description": "Set \"off\" to disable collision-dim: by default a slot dims (--om-widget-opacity-dimmed, 0.35) while an open <om-overlay> popup covers it, rather than the popup dodging.",
          "values": [
            {
              "name": "off"
            }
          ]
        },
        {
          "name": "validate",
          "description": "Run manifest validation and show the on-page error panel."
        },
        {
          "name": "map-id",
          "description": "Optional authored UUID identifying this map artifact (telemetry dedup across visits/pages — not a visitor id). Opt-out: delete it."
        },
        {
          "name": "license-key",
          "description": "OnlyMapJS license token (om_live_…) — lifts the free-tier limits (5 layers / 25k rows per layer) and removes the badge. Publishable, origin-restricted; or call OmMap.configureLicense once."
        },
        {
          "name": "telemetry",
          "description": "Set \"off\" to disable usage telemetry for this map (global opt-out: OmMap.configureTelemetry).",
          "values": [
            {
              "name": "off"
            }
          ]
        },
        {
          "name": "headless",
          "description": "No renderer — parsing/IR only (tests, SSR)."
        },
        {
          "name": "width",
          "description": "Headless viewport width (px)."
        },
        {
          "name": "height",
          "description": "Headless viewport height (px)."
        }
      ],
      "references": [
        {
          "name": "README",
          "url": "https://github.com/NikaGeospatial/onlymapjs/blob/main/README.md"
        }
      ]
    },
    {
      "name": "om-layer",
      "description": "A deck.gl layer declared as markup — attributes map to props (kebab-case), get-* attributes compile as accessors.",
      "attributes": [
        {
          "name": "id",
          "description": "Layer id — referenced by behaviors, steps, widgets, and overlay anchors."
        },
        {
          "name": "type",
          "description": "deck.gl layer class.",
          "values": [
            {
              "name": "A5Layer"
            },
            {
              "name": "ArcLayer"
            },
            {
              "name": "BIMLayer"
            },
            {
              "name": "BitmapLayer"
            },
            {
              "name": "COGLayer"
            },
            {
              "name": "ColumnLayer"
            },
            {
              "name": "ContourLayer"
            },
            {
              "name": "GeoJsonLayer"
            },
            {
              "name": "GeohashLayer"
            },
            {
              "name": "GreatCircleLayer"
            },
            {
              "name": "GridCellLayer"
            },
            {
              "name": "GridLayer"
            },
            {
              "name": "H3ClusterLayer"
            },
            {
              "name": "H3HexagonLayer"
            },
            {
              "name": "HeatmapLayer"
            },
            {
              "name": "HexagonLayer"
            },
            {
              "name": "IconLayer"
            },
            {
              "name": "ImageOverlay"
            },
            {
              "name": "LineLayer"
            },
            {
              "name": "MVTLayer"
            },
            {
              "name": "PathLayer"
            },
            {
              "name": "PointCloudLayer"
            },
            {
              "name": "PolygonLayer"
            },
            {
              "name": "PopupLayer"
            },
            {
              "name": "QuadkeyLayer"
            },
            {
              "name": "Route"
            },
            {
              "name": "S2Layer"
            },
            {
              "name": "ScatterplotLayer"
            },
            {
              "name": "ScenegraphLayer"
            },
            {
              "name": "ScreenGridLayer"
            },
            {
              "name": "SimpleMeshLayer"
            },
            {
              "name": "SolidPolygonLayer"
            },
            {
              "name": "TerrainLayer"
            },
            {
              "name": "TextLayer"
            },
            {
              "name": "Tile3DLayer"
            },
            {
              "name": "TileLayer"
            },
            {
              "name": "Tracking"
            },
            {
              "name": "TripsLayer"
            },
            {
              "name": "ZarrLayer"
            }
          ]
        },
        {
          "name": "data",
          "description": "Data URL (JSON, GeoJSON, CSV/TSV, Arrow/GeoArrow IPC, Shapefile .shp, KML, GPX, FlatGeobuf .fgb, GeoParquet .parquet, CityJSON) or wss:// stream; omit for inline <script type=\"application/json\">."
        },
        {
          "name": "label",
          "description": "Human-readable name shown in the legend and layer list."
        },
        {
          "name": "color",
          "description": "Shorthand fill color (hex or CSS color) — also the legend swatch."
        },
        {
          "name": "visible",
          "description": "Layer visibility.",
          "values": [
            {
              "name": "true"
            },
            {
              "name": "false"
            }
          ]
        },
        {
          "name": "opacity",
          "description": "Layer opacity 0–1."
        },
        {
          "name": "pickable",
          "description": "Enables hover/click picking for behaviors and tooltips."
        },
        {
          "name": "transition",
          "description": "GPU prop transitions, e.g. \"get-fill-color 800ms, get-radius 400ms\"."
        },
        {
          "name": "filter-field",
          "description": "GPU filter field (DataFilterExtension) — pair with filter-range. Single dimension; for more than one, use filter-fields instead."
        },
        {
          "name": "filter-range",
          "description": "Filter range \"[min, max]\" for filter-field."
        },
        {
          "name": "filter-soft-range",
          "description": "Soft edges \"[min, max]\" for the filter."
        },
        {
          "name": "filter-fields",
          "description": "Multi-dimension GPU filter (up to 4) — JSON array of {field, range, softRange?} objects, e.g. '[{\"field\":\"mag\",\"range\":[3,9]}]'. Wins over filter-field/filter-range if both are set."
        },
        {
          "name": "filter-category",
          "description": "Categorical GPU filter field — pair with filter-categories. Single dimension; for more than one, use filter-category-fields instead."
        },
        {
          "name": "filter-categories",
          "description": "JSON array of categories to keep, for filter-category."
        },
        {
          "name": "filter-category-fields",
          "description": "Multi-dimension categorical GPU filter (up to 4) — JSON array of {field, categories} objects, e.g. '[{\"field\":\"fuel\",\"categories\":[\"Coal\",\"Gas\"]}]'. Wins over filter-category/filter-categories if both are set."
        },
        {
          "name": "classify-by",
          "description": "Classified symbology: the numeric field to compute class breaks from (quantile/equal-interval/jenks). Installs a fill-color accessor + auto legend; an authored get-fill-color/color wins."
        },
        {
          "name": "classify-scale",
          "description": "Classification mode: quantile (default), equal-interval, or jenks."
        },
        {
          "name": "classify-classes",
          "description": "Number of classes, 2–12 (default 5)."
        },
        {
          "name": "classify-ramp",
          "description": "Named color ramp for classification: viridis (default), plasma, inferno, magma, cividis, turbo, blues, greens, oranges, purples, reds, ylorrd, rdbu, spectral."
        },
        {
          "name": "dash",
          "description": "Dashed line pattern \"[dashLength, gapLength]\" (or \"6 3\") in line-width units. PathLayer/GeoJsonLayer/PolygonLayer/TripsLayer."
        },
        {
          "name": "dash-justified",
          "description": "Stretch each segment's dashes to start and end on a dash (boolean)."
        },
        {
          "name": "highlighted-id",
          "description": "Feature id to highlight (set by the highlight-feature action)."
        },
        {
          "name": "terrain",
          "description": "Behavior under an active map terrain: drape onto the surface, offset (sit on it — the 3D-model default), or off. Absent = the type default.",
          "values": [
            {
              "name": "drape"
            },
            {
              "name": "offset"
            },
            {
              "name": "off"
            }
          ]
        },
        {
          "name": "clip",
          "description": "Opt out of the map's active clip box (<om-map clip-box-min/max>) with \"off\" — clipping applies to every layer by default once a box is configured.",
          "values": [
            {
              "name": "off"
            }
          ]
        },
        {
          "name": "snap",
          "description": "Opt out of the map's active XY snapping (<om-map snap>) with \"off\" — snapping searches every layer's own geometry by default once enabled, including a BIMLayer's edge overlay.",
          "values": [
            {
              "name": "off"
            }
          ]
        },
        {
          "name": "key",
          "description": "Stream entity identity field — messages upsert by this key (wss data)."
        },
        {
          "name": "flush",
          "description": "Stream burst coalescing interval (default 250ms)."
        },
        {
          "name": "refresh",
          "description": "Polling interval for REST snapshots, e.g. \"5s\" — each poll replaces the data."
        },
        {
          "name": "source",
          "description": "registerSource decoder plugin name for stream messages."
        },
        {
          "name": "site-origin",
          "description": "Georeferencing (Tile3DLayer, PathLayer): where the model sits, \"[lng, lat]\" or \"[lng, lat, elevation]\". Overrides a tileset's baked position; required to place a PathLayer of local metres."
        },
        {
          "name": "site-heading",
          "description": "Georeferencing: bearing in degrees clockwise from true north. On its own, rotates the model where it stands."
        },
        {
          "name": "site-scale",
          "description": "Georeferencing: uniform scale multiplier (default 1)."
        },
        {
          "name": "anchor",
          "description": "anchor=\"surface\": anchor each row INSIDE its own polygon (point-on-surface) — on-map labels/annotations with no authored coordinates. An authored get-position wins.",
          "values": [
            {
              "name": "surface"
            }
          ]
        },
        {
          "name": "get-position",
          "description": "Accessor for deck.gl getPosition — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-fill-color",
          "description": "Accessor for deck.gl getFillColor — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-line-color",
          "description": "Accessor for deck.gl getLineColor — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-radius",
          "description": "Accessor for deck.gl getRadius — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "radius",
          "description": "deck.gl undefined."
        },
        {
          "name": "radius-units",
          "description": "deck.gl radiusUnits."
        },
        {
          "name": "radius-min-pixels",
          "description": "deck.gl radiusMinPixels."
        },
        {
          "name": "line-width-min-pixels",
          "description": "deck.gl lineWidthMinPixels."
        },
        {
          "name": "stroked",
          "description": "deck.gl stroked."
        },
        {
          "name": "filled",
          "description": "deck.gl filled."
        },
        {
          "name": "operation",
          "description": "deck.gl operation."
        },
        {
          "name": "coordinate-system",
          "description": "deck.gl coordinateSystem."
        },
        {
          "name": "coordinate-origin",
          "description": "deck.gl coordinateOrigin."
        },
        {
          "name": "model-matrix",
          "description": "deck.gl modelMatrix."
        },
        {
          "name": "wrap-longitude",
          "description": "deck.gl wrapLongitude."
        },
        {
          "name": "position-format",
          "description": "deck.gl positionFormat."
        },
        {
          "name": "color-format",
          "description": "deck.gl colorFormat."
        },
        {
          "name": "parameters",
          "description": "deck.gl parameters."
        },
        {
          "name": "load-options",
          "description": "deck.gl loadOptions."
        },
        {
          "name": "transitions",
          "description": "deck.gl transitions."
        },
        {
          "name": "extensions",
          "description": "deck.gl extensions."
        },
        {
          "name": "loaders",
          "description": "deck.gl loaders."
        },
        {
          "name": "highlighted-object-index",
          "description": "deck.gl highlightedObjectIndex."
        },
        {
          "name": "auto-highlight",
          "description": "deck.gl autoHighlight."
        },
        {
          "name": "highlight-color",
          "description": "deck.gl highlightColor."
        },
        {
          "name": "radius-scale",
          "description": "deck.gl radiusScale."
        },
        {
          "name": "radius-max-pixels",
          "description": "deck.gl radiusMaxPixels."
        },
        {
          "name": "line-width-units",
          "description": "deck.gl lineWidthUnits."
        },
        {
          "name": "line-width-scale",
          "description": "deck.gl lineWidthScale."
        },
        {
          "name": "line-width-max-pixels",
          "description": "deck.gl lineWidthMaxPixels."
        },
        {
          "name": "billboard",
          "description": "deck.gl billboard."
        },
        {
          "name": "antialiasing",
          "description": "deck.gl antialiasing."
        },
        {
          "name": "get-line-width",
          "description": "Accessor for deck.gl getLineWidth — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-pixel-offset",
          "description": "Accessor for deck.gl getPixelOffset — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-point-radius",
          "description": "Accessor for deck.gl getPointRadius — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "point-radius-units",
          "description": "deck.gl pointRadiusUnits."
        },
        {
          "name": "point-radius-min-pixels",
          "description": "deck.gl pointRadiusMinPixels."
        },
        {
          "name": "get-elevation",
          "description": "Accessor for deck.gl getElevation — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "extruded",
          "description": "deck.gl extruded."
        },
        {
          "name": "wireframe",
          "description": "deck.gl wireframe."
        },
        {
          "name": "point-radius-max-pixels",
          "description": "deck.gl pointRadiusMaxPixels."
        },
        {
          "name": "point-radius-scale",
          "description": "deck.gl pointRadiusScale."
        },
        {
          "name": "point-antialiasing",
          "description": "deck.gl pointAntialiasing."
        },
        {
          "name": "point-billboard",
          "description": "deck.gl pointBillboard."
        },
        {
          "name": "icon-atlas",
          "description": "deck.gl iconAtlas."
        },
        {
          "name": "icon-mapping",
          "description": "deck.gl iconMapping."
        },
        {
          "name": "icon-size-max-pixels",
          "description": "deck.gl iconSizeMaxPixels."
        },
        {
          "name": "icon-size-min-pixels",
          "description": "deck.gl iconSizeMinPixels."
        },
        {
          "name": "icon-size-scale",
          "description": "deck.gl iconSizeScale."
        },
        {
          "name": "icon-size-units",
          "description": "deck.gl iconSizeUnits."
        },
        {
          "name": "icon-alpha-cutoff",
          "description": "deck.gl iconAlphaCutoff."
        },
        {
          "name": "icon-billboard",
          "description": "deck.gl iconBillboard."
        },
        {
          "name": "get-icon",
          "description": "Accessor for deck.gl getIcon — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-icon-angle",
          "description": "Accessor for deck.gl getIconAngle — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-icon-color",
          "description": "Accessor for deck.gl getIconColor — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-icon-pixel-offset",
          "description": "Accessor for deck.gl getIconPixelOffset — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-icon-size",
          "description": "Accessor for deck.gl getIconSize — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "text-size-max-pixels",
          "description": "deck.gl textSizeMaxPixels."
        },
        {
          "name": "text-size-min-pixels",
          "description": "deck.gl textSizeMinPixels."
        },
        {
          "name": "text-size-scale",
          "description": "deck.gl textSizeScale."
        },
        {
          "name": "text-size-units",
          "description": "deck.gl textSizeUnits."
        },
        {
          "name": "text-background",
          "description": "deck.gl textBackground."
        },
        {
          "name": "text-background-padding",
          "description": "deck.gl textBackgroundPadding."
        },
        {
          "name": "text-font-family",
          "description": "deck.gl textFontFamily."
        },
        {
          "name": "text-font-weight",
          "description": "deck.gl textFontWeight."
        },
        {
          "name": "text-line-height",
          "description": "deck.gl textLineHeight."
        },
        {
          "name": "text-max-width",
          "description": "deck.gl textMaxWidth."
        },
        {
          "name": "text-outline-color",
          "description": "deck.gl textOutlineColor."
        },
        {
          "name": "text-outline-width",
          "description": "deck.gl textOutlineWidth."
        },
        {
          "name": "text-word-break",
          "description": "deck.gl textWordBreak."
        },
        {
          "name": "text-character-set",
          "description": "deck.gl textCharacterSet."
        },
        {
          "name": "text-billboard",
          "description": "deck.gl textBillboard."
        },
        {
          "name": "text-font-settings",
          "description": "deck.gl textFontSettings."
        },
        {
          "name": "get-text",
          "description": "Accessor for deck.gl getText — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-text-angle",
          "description": "Accessor for deck.gl getTextAngle — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-text-color",
          "description": "Accessor for deck.gl getTextColor — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-text-pixel-offset",
          "description": "Accessor for deck.gl getTextPixelOffset — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-text-size",
          "description": "Accessor for deck.gl getTextSize — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-text-anchor",
          "description": "Accessor for deck.gl getTextAnchor — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-text-alignment-baseline",
          "description": "Accessor for deck.gl getTextAlignmentBaseline — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-text-background-color",
          "description": "Accessor for deck.gl getTextBackgroundColor — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-text-border-color",
          "description": "Accessor for deck.gl getTextBorderColor — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-text-border-width",
          "description": "Accessor for deck.gl getTextBorderWidth — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "line-joint-rounded",
          "description": "deck.gl lineJointRounded."
        },
        {
          "name": "line-cap-rounded",
          "description": "deck.gl lineCapRounded."
        },
        {
          "name": "line-miter-limit",
          "description": "deck.gl lineMiterLimit."
        },
        {
          "name": "line-billboard",
          "description": "deck.gl lineBillboard."
        },
        {
          "name": "elevation-scale",
          "description": "deck.gl elevationScale."
        },
        {
          "name": "material",
          "description": "deck.gl material."
        },
        {
          "name": "point-type",
          "description": "deck.gl pointType."
        },
        {
          "name": "get-polygon",
          "description": "Accessor for deck.gl getPolygon — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "full3d",
          "description": "deck.gl _full3d."
        },
        {
          "name": "get-subtext",
          "description": "Accessor for deck.gl getSubtext — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-color",
          "description": "Accessor for deck.gl getColor — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-size",
          "description": "Accessor for deck.gl getSize — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "layout",
          "description": "deck.gl layout."
        },
        {
          "name": "min-zoom",
          "description": "deck.gl minZoom."
        },
        {
          "name": "max-zoom",
          "description": "deck.gl maxZoom."
        },
        {
          "name": "scenegraph",
          "description": "deck.gl scenegraph."
        },
        {
          "name": "get-orientation",
          "description": "Accessor for deck.gl getOrientation — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-scale",
          "description": "Accessor for deck.gl getScale — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-translation",
          "description": "Accessor for deck.gl getTranslation — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "size-scale",
          "description": "deck.gl sizeScale."
        },
        {
          "name": "size-min-pixels",
          "description": "deck.gl sizeMinPixels."
        },
        {
          "name": "size-max-pixels",
          "description": "deck.gl sizeMaxPixels."
        },
        {
          "name": "lighting",
          "description": "deck.gl _lighting."
        },
        {
          "name": "get-transform-matrix",
          "description": "Accessor for deck.gl getTransformMatrix — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "tileset",
          "description": "deck.gl data."
        },
        {
          "name": "maximum-screen-space-error",
          "description": "deck.gl loadOptions.tileset.maximumScreenSpaceError."
        },
        {
          "name": "maximum-memory-usage",
          "description": "deck.gl loadOptions.tileset.maximumMemoryUsage."
        },
        {
          "name": "view-distance-scale",
          "description": "deck.gl loadOptions.tileset.viewDistanceScale."
        },
        {
          "name": "point-size",
          "description": "deck.gl pointSize."
        },
        {
          "name": "pick-features",
          "description": "deck.gl pickFeatures."
        },
        {
          "name": "feature-id-property",
          "description": "deck.gl featureIdProperty."
        },
        {
          "name": "feature-styles",
          "description": "deck.gl featureStyles."
        },
        {
          "name": "feature-color-by",
          "description": "deck.gl featureColorBy."
        },
        {
          "name": "feature-color-scale",
          "description": "deck.gl featureColorScale."
        },
        {
          "name": "feature-palette",
          "description": "deck.gl featurePalette."
        },
        {
          "name": "feature-color-strength",
          "description": "deck.gl featureColorStrength."
        },
        {
          "name": "feature-filter-field",
          "description": "deck.gl featureFilterField."
        },
        {
          "name": "isolate-features",
          "description": "deck.gl isolateFeatures."
        },
        {
          "name": "hide-features",
          "description": "deck.gl hideFeatures."
        },
        {
          "name": "ghost-features",
          "description": "deck.gl ghostFeatures."
        },
        {
          "name": "ghost-opacity",
          "description": "deck.gl ghostOpacity."
        },
        {
          "name": "get-point-color",
          "description": "Accessor for deck.gl getPointColor — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "loader",
          "description": "deck.gl loader."
        },
        {
          "name": "src",
          "description": "deck.gl src."
        },
        {
          "name": "geometry",
          "description": "deck.gl geometry."
        },
        {
          "name": "origin",
          "description": "deck.gl origin."
        },
        {
          "name": "destination",
          "description": "deck.gl destination."
        },
        {
          "name": "waypoints",
          "description": "deck.gl waypoints."
        },
        {
          "name": "provider",
          "description": "deck.gl provider."
        },
        {
          "name": "profile",
          "description": "deck.gl profile."
        },
        {
          "name": "casing-color",
          "description": "deck.gl casingColor."
        },
        {
          "name": "tail",
          "description": "deck.gl tail."
        },
        {
          "name": "tail-color",
          "description": "deck.gl tailColor."
        },
        {
          "name": "progress-from",
          "description": "deck.gl progressFrom."
        },
        {
          "name": "follow",
          "description": "deck.gl follow."
        },
        {
          "name": "bearing-field",
          "description": "deck.gl bearingField."
        },
        {
          "name": "size",
          "description": "deck.gl size."
        },
        {
          "name": "icon",
          "description": "deck.gl icon."
        },
        {
          "name": "interpolate-ms",
          "description": "deck.gl interpolateMs."
        },
        {
          "name": "georeference",
          "description": "deck.gl georeference."
        },
        {
          "name": "sensor-width-mm",
          "description": "deck.gl sensorWidthMm."
        },
        {
          "name": "sensor-height-mm",
          "description": "deck.gl sensorHeightMm."
        },
        {
          "name": "focal-length-mm",
          "description": "deck.gl focalLengthMm."
        },
        {
          "name": "bounds",
          "description": "deck.gl bounds."
        },
        {
          "name": "metadata",
          "description": "deck.gl metadata."
        },
        {
          "name": "depth-test",
          "description": "deck.gl parameters.depthTest."
        },
        {
          "name": "image",
          "description": "deck.gl image."
        },
        {
          "name": "desaturate",
          "description": "deck.gl desaturate."
        },
        {
          "name": "transparent-color",
          "description": "deck.gl transparentColor."
        },
        {
          "name": "tint-color",
          "description": "deck.gl tintColor."
        },
        {
          "name": "texture-parameters",
          "description": "deck.gl textureParameters."
        },
        {
          "name": "min",
          "description": "deck.gl rescaleMin."
        },
        {
          "name": "max",
          "description": "deck.gl rescaleMax."
        },
        {
          "name": "colormap",
          "description": "deck.gl colormap."
        },
        {
          "name": "nodata",
          "description": "deck.gl nodataOverride."
        },
        {
          "name": "variable",
          "description": "deck.gl variable."
        },
        {
          "name": "select",
          "description": "deck.gl select."
        },
        {
          "name": "crs",
          "description": "deck.gl crs."
        },
        {
          "name": "spatial-dims",
          "description": "deck.gl spatialDims."
        },
        {
          "name": "get-source-position",
          "description": "Accessor for deck.gl getSourcePosition — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-target-position",
          "description": "Accessor for deck.gl getTargetPosition — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-source-color",
          "description": "Accessor for deck.gl getSourceColor — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-target-color",
          "description": "Accessor for deck.gl getTargetColor — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-width",
          "description": "Accessor for deck.gl getWidth — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-height",
          "description": "Accessor for deck.gl getHeight — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-tilt",
          "description": "Accessor for deck.gl getTilt — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "great-circle",
          "description": "deck.gl greatCircle."
        },
        {
          "name": "num-segments",
          "description": "deck.gl numSegments."
        },
        {
          "name": "width-units",
          "description": "deck.gl widthUnits."
        },
        {
          "name": "width-scale",
          "description": "deck.gl widthScale."
        },
        {
          "name": "width-min-pixels",
          "description": "deck.gl widthMinPixels."
        },
        {
          "name": "width-max-pixels",
          "description": "deck.gl widthMaxPixels."
        },
        {
          "name": "_image-coordinate-system",
          "description": "deck.gl _imageCoordinateSystem."
        },
        {
          "name": "disk-resolution",
          "description": "deck.gl diskResolution."
        },
        {
          "name": "vertices",
          "description": "deck.gl vertices."
        },
        {
          "name": "angle",
          "description": "deck.gl angle."
        },
        {
          "name": "offset",
          "description": "deck.gl offset."
        },
        {
          "name": "coverage",
          "description": "deck.gl coverage."
        },
        {
          "name": "flat-shading",
          "description": "deck.gl flatShading."
        },
        {
          "name": "cell-size",
          "description": "deck.gl cellSize."
        },
        {
          "name": "size-units",
          "description": "deck.gl sizeUnits."
        },
        {
          "name": "size-basis",
          "description": "deck.gl sizeBasis."
        },
        {
          "name": "alpha-cutoff",
          "description": "deck.gl alphaCutoff."
        },
        {
          "name": "get-angle",
          "description": "Accessor for deck.gl getAngle — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "joint-rounded",
          "description": "deck.gl jointRounded."
        },
        {
          "name": "cap-rounded",
          "description": "deck.gl capRounded."
        },
        {
          "name": "miter-limit",
          "description": "deck.gl miterLimit."
        },
        {
          "name": "_path-type",
          "description": "deck.gl _pathType."
        },
        {
          "name": "get-path",
          "description": "Accessor for deck.gl getPath — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-normal",
          "description": "Accessor for deck.gl getNormal — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "_normalize",
          "description": "deck.gl _normalize."
        },
        {
          "name": "_winding-order",
          "description": "deck.gl _windingOrder."
        },
        {
          "name": "background",
          "description": "deck.gl background."
        },
        {
          "name": "get-background-color",
          "description": "Accessor for deck.gl getBackgroundColor — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-border-color",
          "description": "Accessor for deck.gl getBorderColor — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-border-width",
          "description": "Accessor for deck.gl getBorderWidth — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "background-border-radius",
          "description": "deck.gl backgroundBorderRadius."
        },
        {
          "name": "background-padding",
          "description": "deck.gl backgroundPadding."
        },
        {
          "name": "character-set",
          "description": "deck.gl characterSet."
        },
        {
          "name": "font-family",
          "description": "deck.gl fontFamily."
        },
        {
          "name": "font-weight",
          "description": "deck.gl fontWeight."
        },
        {
          "name": "line-height",
          "description": "deck.gl lineHeight."
        },
        {
          "name": "outline-width",
          "description": "deck.gl outlineWidth."
        },
        {
          "name": "outline-color",
          "description": "deck.gl outlineColor."
        },
        {
          "name": "font-settings",
          "description": "deck.gl fontSettings."
        },
        {
          "name": "word-break",
          "description": "deck.gl wordBreak."
        },
        {
          "name": "max-width",
          "description": "deck.gl maxWidth."
        },
        {
          "name": "content-cutoff-pixels",
          "description": "deck.gl contentCutoffPixels."
        },
        {
          "name": "content-align-horizontal",
          "description": "deck.gl contentAlignHorizontal."
        },
        {
          "name": "content-align-vertical",
          "description": "deck.gl contentAlignVertical."
        },
        {
          "name": "get-alignment-baseline",
          "description": "Accessor for deck.gl getAlignmentBaseline — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-content-box",
          "description": "Accessor for deck.gl getContentBox — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-pentagon",
          "description": "Accessor for deck.gl getPentagon — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-geohash",
          "description": "Accessor for deck.gl getGeohash — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-hexagons",
          "description": "Accessor for deck.gl getHexagons — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "high-precision",
          "description": "deck.gl highPrecision."
        },
        {
          "name": "center-hexagon",
          "description": "deck.gl centerHexagon."
        },
        {
          "name": "get-hexagon",
          "description": "Accessor for deck.gl getHexagon — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "extent",
          "description": "deck.gl extent."
        },
        {
          "name": "tile-size",
          "description": "deck.gl tileSize."
        },
        {
          "name": "max-cache-size",
          "description": "deck.gl maxCacheSize."
        },
        {
          "name": "max-cache-byte-size",
          "description": "deck.gl maxCacheByteSize."
        },
        {
          "name": "refinement-strategy",
          "description": "deck.gl refinementStrategy."
        },
        {
          "name": "z-range",
          "description": "deck.gl zRange."
        },
        {
          "name": "max-requests",
          "description": "deck.gl maxRequests."
        },
        {
          "name": "debounce-time",
          "description": "deck.gl debounceTime."
        },
        {
          "name": "zoom-offset",
          "description": "deck.gl zoomOffset."
        },
        {
          "name": "visible-min-zoom",
          "description": "deck.gl visibleMinZoom."
        },
        {
          "name": "visible-max-zoom",
          "description": "deck.gl visibleMaxZoom."
        },
        {
          "name": "_full3d",
          "description": "deck.gl _full3d."
        },
        {
          "name": "unique-id-property",
          "description": "deck.gl uniqueIdProperty."
        },
        {
          "name": "highlighted-feature-id",
          "description": "deck.gl highlightedFeatureId."
        },
        {
          "name": "binary",
          "description": "deck.gl binary."
        },
        {
          "name": "get-quadkey",
          "description": "Accessor for deck.gl getQuadkey — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-s2-token",
          "description": "Accessor for deck.gl getS2Token — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "elevation-data",
          "description": "deck.gl elevationData."
        },
        {
          "name": "texture",
          "description": "deck.gl texture."
        },
        {
          "name": "mesh-max-error",
          "description": "deck.gl meshMaxError."
        },
        {
          "name": "elevation-decoder",
          "description": "deck.gl elevationDecoder."
        },
        {
          "name": "worker-url",
          "description": "deck.gl workerUrl."
        },
        {
          "name": "fade-trail",
          "description": "deck.gl fadeTrail."
        },
        {
          "name": "trail-length",
          "description": "deck.gl trailLength."
        },
        {
          "name": "current-time",
          "description": "deck.gl currentTime."
        },
        {
          "name": "get-timestamps",
          "description": "Accessor for deck.gl getTimestamps — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "grid-origin",
          "description": "deck.gl gridOrigin."
        },
        {
          "name": "get-weight",
          "description": "Accessor for deck.gl getWeight — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "gpu-aggregation",
          "description": "deck.gl gpuAggregation."
        },
        {
          "name": "aggregation",
          "description": "deck.gl aggregation."
        },
        {
          "name": "contours",
          "description": "deck.gl contours."
        },
        {
          "name": "z-offset",
          "description": "deck.gl zOffset."
        },
        {
          "name": "color-domain",
          "description": "deck.gl colorDomain."
        },
        {
          "name": "color-range",
          "description": "deck.gl colorRange."
        },
        {
          "name": "get-color-value",
          "description": "Accessor for deck.gl getColorValue — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-color-weight",
          "description": "Accessor for deck.gl getColorWeight — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "color-aggregation",
          "description": "deck.gl colorAggregation."
        },
        {
          "name": "lower-percentile",
          "description": "deck.gl lowerPercentile."
        },
        {
          "name": "upper-percentile",
          "description": "deck.gl upperPercentile."
        },
        {
          "name": "color-scale-type",
          "description": "deck.gl colorScaleType."
        },
        {
          "name": "elevation-domain",
          "description": "deck.gl elevationDomain."
        },
        {
          "name": "elevation-range",
          "description": "deck.gl elevationRange."
        },
        {
          "name": "get-elevation-value",
          "description": "Accessor for deck.gl getElevationValue — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "get-elevation-weight",
          "description": "Accessor for deck.gl getElevationWeight — expression language: $field, scale(), formatDate(), arithmetic."
        },
        {
          "name": "elevation-aggregation",
          "description": "deck.gl elevationAggregation."
        },
        {
          "name": "elevation-lower-percentile",
          "description": "deck.gl elevationLowerPercentile."
        },
        {
          "name": "elevation-upper-percentile",
          "description": "deck.gl elevationUpperPercentile."
        },
        {
          "name": "elevation-scale-type",
          "description": "deck.gl elevationScaleType."
        },
        {
          "name": "intensity",
          "description": "deck.gl intensity."
        },
        {
          "name": "radius-pixels",
          "description": "deck.gl radiusPixels."
        },
        {
          "name": "threshold",
          "description": "deck.gl threshold."
        },
        {
          "name": "weights-texture-size",
          "description": "deck.gl weightsTextureSize."
        },
        {
          "name": "debounce-timeout",
          "description": "deck.gl debounceTimeout."
        },
        {
          "name": "cell-size-pixels",
          "description": "deck.gl cellSizePixels."
        },
        {
          "name": "cell-margin-pixels",
          "description": "deck.gl cellMarginPixels."
        },
        {
          "name": "mesh",
          "description": "deck.gl mesh."
        },
        {
          "name": "_instanced",
          "description": "deck.gl _instanced."
        }
      ]
    },
    {
      "name": "om-overlay",
      "description": "Rich HTML anchored to the map: a static coordinate, the current selection, or a feature's own geometry.",
      "attributes": [
        {
          "name": "id",
          "description": "Overlay id — referenced by show/hide-overlay."
        },
        {
          "name": "anchor",
          "description": "Static anchor \"[lng, lat]\"."
        },
        {
          "name": "anchor-from",
          "description": "Dynamic anchor source.",
          "values": [
            {
              "name": "selection"
            }
          ]
        },
        {
          "name": "anchor-layer",
          "description": "Anchor to a feature of this layer (with anchor-feature-id)."
        },
        {
          "name": "anchor-feature-id",
          "description": "Feature id to anchor to — bbox center for polygons/lines."
        },
        {
          "name": "anchor-offset",
          "description": "Attachment point relative to the anchor.",
          "values": [
            {
              "name": "top-left"
            },
            {
              "name": "top-center"
            },
            {
              "name": "top-right"
            },
            {
              "name": "center-left"
            },
            {
              "name": "center"
            },
            {
              "name": "center-right"
            },
            {
              "name": "bottom-left"
            },
            {
              "name": "bottom-center"
            },
            {
              "name": "bottom-right"
            }
          ]
        },
        {
          "name": "visible",
          "description": "Overlay visibility.",
          "values": [
            {
              "name": "true"
            },
            {
              "name": "false"
            }
          ]
        },
        {
          "name": "layer",
          "description": "Scope selection-anchored overlays to one layer's picks."
        },
        {
          "name": "selection-type",
          "description": "Scope selection-anchored overlays to one pick type — \"click\" keeps a click-opened popup from following hover picks; \"hover\" is the mirror. Absent: every pick applies.",
          "values": [
            {
              "name": "click"
            },
            {
              "name": "hover"
            }
          ]
        },
        {
          "name": "clip-to-map",
          "description": "Hide the overlay when its own BOX would spill past the map viewport, not just when its anchor leaves (the default). Opt-in: an overhanging absolutely-positioned box inflates the page's scrollable overflow, and the resulting scrollbar → map resize → reprojection loop shows as view jitter. Use it for small transient tips that track the cursor; an authored popup near an edge normally wants to keep showing its visible half."
        }
      ],
      "references": [
        {
          "name": "Stories & overlays",
          "url": "https://github.com/NikaGeospatial/onlymapjs/blob/main/docs/stories.md"
        }
      ]
    },
    {
      "name": "om-fallback",
      "description": "Static fallback shown only when the library never boots — JS-disabled contexts like chat-app/email file previews (iOS QuickLook), file managers, sandboxed webviews. Direct child of <om-map>; hidden automatically once the map upgrades. Good practice on any page that may be shared as a file. Without one, the stylesheet shows a text-only default banner. Requires onlymapjs.css to load without JS (link tag / bundled / inlined).",
      "attributes": [],
      "references": [
        {
          "name": "README",
          "url": "https://github.com/NikaGeospatial/onlymapjs/blob/main/README.md"
        }
      ]
    },
    {
      "name": "om-behavior",
      "description": "Declarative event → action wiring. Every other attribute becomes a payload key (kebab→camel).",
      "attributes": [
        {
          "name": "on",
          "description": "Trigger event.",
          "values": [
            {
              "name": "click"
            },
            {
              "name": "hover"
            },
            {
              "name": "drag"
            },
            {
              "name": "load"
            },
            {
              "name": "data-loaded"
            }
          ]
        },
        {
          "name": "layer",
          "description": "Only picks on this layer trigger the behavior."
        },
        {
          "name": "action",
          "description": "Action to dispatch.",
          "values": [
            {
              "name": "toggle-layer"
            },
            {
              "name": "zoom-in"
            },
            {
              "name": "zoom-out"
            },
            {
              "name": "filter-layer"
            },
            {
              "name": "highlight-feature"
            },
            {
              "name": "fade"
            },
            {
              "name": "pulse"
            },
            {
              "name": "populate"
            },
            {
              "name": "trace"
            },
            {
              "name": "story-play"
            },
            {
              "name": "story-pause"
            },
            {
              "name": "story-seek"
            },
            {
              "name": "fly-to"
            },
            {
              "name": "zoom-to-feature"
            },
            {
              "name": "show-overlay"
            },
            {
              "name": "hide-overlay"
            },
            {
              "name": "show-tooltip"
            },
            {
              "name": "hide-tooltip"
            },
            {
              "name": "draw-mode"
            },
            {
              "name": "draw-commit"
            },
            {
              "name": "draw-cancel"
            },
            {
              "name": "draw-delete"
            },
            {
              "name": "draw-clear"
            },
            {
              "name": "draw-config"
            },
            {
              "name": "draw-save"
            },
            {
              "name": "export-region-3d"
            },
            {
              "name": "measure-mode"
            },
            {
              "name": "measure-clear"
            },
            {
              "name": "measure-units"
            },
            {
              "name": "set-basemap"
            },
            {
              "name": "set-lighting"
            },
            {
              "name": "set-terrain"
            },
            {
              "name": "set-clip-box"
            },
            {
              "name": "clip-box-edit"
            },
            {
              "name": "set-widgets-visible"
            },
            {
              "name": "undo"
            },
            {
              "name": "redo"
            },
            {
              "name": "warm-tiles"
            }
          ]
        },
        {
          "name": "target",
          "description": "Target overlay id (show/hide-overlay payload)."
        },
        {
          "name": "template",
          "description": "Tooltip template selector (show-tooltip payload)."
        }
      ]
    },
    {
      "name": "om-widget",
      "description": "Map UI chrome — built-in types or inline <script type=\"om/widget\"> render logic.",
      "attributes": [
        {
          "name": "type",
          "description": "Built-in widget type (omit for a custom scripted widget).",
          "values": [
            {
              "name": "legend"
            },
            {
              "name": "layer-switcher"
            },
            {
              "name": "zoom-controls"
            },
            {
              "name": "scale-bar"
            },
            {
              "name": "attribution"
            },
            {
              "name": "filter"
            },
            {
              "name": "vega-lite"
            },
            {
              "name": "dynamic-chart"
            },
            {
              "name": "player"
            },
            {
              "name": "draw"
            },
            {
              "name": "measure"
            },
            {
              "name": "basemap-switcher"
            },
            {
              "name": "lighting"
            },
            {
              "name": "clip-box"
            },
            {
              "name": "undo-redo"
            },
            {
              "name": "widgets-toggle"
            },
            {
              "name": "time-slider"
            },
            {
              "name": "ifc-browser"
            },
            {
              "name": "ifc-legend"
            },
            {
              "name": "feature-inspector"
            },
            {
              "name": "ifc-inspector"
            },
            {
              "name": "ifc-loader"
            },
            {
              "name": "ifc-clash"
            }
          ]
        },
        {
          "name": "position",
          "description": "Managed slot (8 logical, RTL-aware: top/center/bottom × start/center/end minus center-center), a legacy corner alias (top-left, …), or \"manual\" (author-styled placement — plain block, no forced positioning). Same-slot widgets stack with flush edges and a shared gap.",
          "values": [
            {
              "name": "top-start"
            },
            {
              "name": "top-center"
            },
            {
              "name": "top-end"
            },
            {
              "name": "center-start"
            },
            {
              "name": "center-end"
            },
            {
              "name": "bottom-start"
            },
            {
              "name": "bottom-center"
            },
            {
              "name": "bottom-end"
            },
            {
              "name": "manual"
            },
            {
              "name": "top-left"
            },
            {
              "name": "top-right"
            },
            {
              "name": "bottom-left"
            },
            {
              "name": "bottom-right"
            }
          ]
        },
        {
          "name": "order",
          "description": "Deterministic in-slot ordering (flex order; lower renders first). Default: DOM order."
        },
        {
          "name": "cluster",
          "description": "Set \"false\" to keep a compact button widget (zoom-controls, undo-redo, widgets-toggle) out of the automatic control-group merge with adjacent compact widgets.",
          "values": [
            {
              "name": "false"
            }
          ]
        },
        {
          "name": "fold",
          "description": "Set \"never\" to keep an essential control outside responsive side drawers on narrow maps.",
          "values": [
            {
              "name": "never"
            }
          ]
        },
        {
          "name": "watch",
          "description": "Space-separated watch tokens: viewport, selection, layers, history, basemap, lighting, terrain, widgets, data:<layerId>."
        },
        {
          "name": "layer",
          "description": "Layer id (filter / vega-lite widgets)."
        },
        {
          "name": "field",
          "description": "Data field (filter / vega-lite / time-slider widgets)."
        },
        {
          "name": "window",
          "description": "time-slider widget: sliding-window span in the field's own units (ms for epoch fields). Absent = cumulative reveal from the domain start."
        },
        {
          "name": "duration",
          "description": "time-slider widget: wall time of one full sweep, e.g. \"20s\" (default). Player-widget-free playback over a layer's time field."
        },
        {
          "name": "loop",
          "description": "time-slider widget: restart the sweep from the domain start when it completes."
        },
        {
          "name": "on",
          "description": "dynamic-chart widget: the <om-map> event name to listen for (required), e.g. \"om-measure\"."
        },
        {
          "name": "series-field",
          "description": "dynamic-chart widget: the event.detail field holding the chart's data array (default \"series\")."
        },
        {
          "name": "format",
          "description": "Filter value-label format. Use date for epoch-millisecond fields; default number.",
          "values": [
            {
              "name": "number"
            },
            {
              "name": "date"
            }
          ]
        },
        {
          "name": "date-style",
          "description": "Filter date label style when format=\"date\".",
          "values": [
            {
              "name": "date"
            },
            {
              "name": "datetime"
            },
            {
              "name": "time"
            },
            {
              "name": "iso"
            }
          ]
        },
        {
          "name": "time-zone",
          "description": "Filter date label time zone when format=\"date\": UTC (default), local, or an IANA zone such as Asia/Singapore."
        },
        {
          "name": "story",
          "description": "Story id (player widget)."
        },
        {
          "name": "target",
          "description": "Draw widget: store the sketch feeds — bind a layer with data=\"draw:<target>\"."
        },
        {
          "name": "modes",
          "description": "Draw widget: space-separated tools (point line polygon). Measure widget: space-separated modes (distance area volume) — volume needs terrain on <om-map>.",
          "values": [
            {
              "name": "point line polygon"
            },
            {
              "name": "point"
            },
            {
              "name": "line"
            },
            {
              "name": "polygon"
            },
            {
              "name": "distance area volume"
            },
            {
              "name": "distance"
            },
            {
              "name": "area"
            },
            {
              "name": "volume"
            }
          ]
        },
        {
          "name": "save",
          "description": "Draw widget: how Save persists the GeoJSON.",
          "values": [
            {
              "name": "both"
            },
            {
              "name": "download"
            },
            {
              "name": "file-system"
            }
          ]
        },
        {
          "name": "autosave",
          "description": "Draw widget: localStorage key — mirrors the sketch and restores it on reload."
        },
        {
          "name": "export-3d",
          "description": "Draw widget: adds an \"Export 3D\" button — clips loaded Tile3DLayer/BIMLayer content to the drawn footprint and downloads it. Bare = GLB (default); \"b3dm\" wraps it for Cesium/3D-Tiles pipelines.",
          "values": [
            {
              "name": "glb"
            },
            {
              "name": "b3dm"
            }
          ]
        },
        {
          "name": "fill-color",
          "description": "Draw widget: shades the committed (closed) shape's interior — CSS color (hex/named/rgb()/rgba()) or a JSON [r,g,b,a?] array. Auto-creates a committed-geometry layer bound to the draw target; without this (or line-color), a closed shape has no built-in visual once the in-progress preview clears."
        },
        {
          "name": "line-color",
          "description": "Draw widget: the committed (closed) shape's boundary color — same formats as fill-color. Given alone, a translucent fill in the same hue is derived automatically so the shape still reads as an area, not just an outline."
        },
        {
          "name": "units",
          "description": "Measure / scale-bar widget: unit system for length and area.",
          "values": [
            {
              "name": "metric"
            },
            {
              "name": "imperial"
            },
            {
              "name": "nautical"
            }
          ]
        },
        {
          "name": "profile",
          "description": "Measure widget: volume-mode attribute — closing a footprint also samples elevation around its own perimeter, for a paired dynamic-chart widget reading the om-measure event's profileSeries field. No effect without \"volume\" in modes."
        },
        {
          "name": "density",
          "description": "Measure widget: volume-mode attribute — material density for a tonnage readout (t/m³ metric, lb/yd³ imperial). Omit to skip tonnage reporting."
        },
        {
          "name": "swell",
          "description": "Measure widget: volume-mode attribute — bulking multiplier applied to the reported Cut volume (excavated material occupies more space loose than in situ). Default 1 (no adjustment)."
        },
        {
          "name": "shrink",
          "description": "Measure widget: volume-mode attribute — compaction multiplier applied to the reported Fill volume. Default 1 (no adjustment)."
        },
        {
          "name": "deadband",
          "description": "Measure widget: volume-mode attribute — Cut/Fill below this many m³ reports as zero, filtering drag noise near zero height. Default 0 (no deadband)."
        },
        {
          "name": "base-surface",
          "description": "Measure widget: volume-mode base-surface strategy. \"custom\" (default) is the draggable gizmo's target plane; \"triangulated\" (boundary TIN), \"plane\" (least-squares fit), \"lowest\"/\"highest\"/\"average\" derive the base from the footprint's own boundary elevations — stockpile-style, no gizmo.",
          "values": [
            {
              "name": "custom"
            },
            {
              "name": "triangulated"
            },
            {
              "name": "plane"
            },
            {
              "name": "lowest"
            },
            {
              "name": "highest"
            },
            {
              "name": "average"
            }
          ]
        },
        {
          "name": "options",
          "description": "Basemap-switcher: space-separated preset names to offer (default: every keyless registered preset)."
        },
        {
          "name": "fields",
          "description": "IFC widgets: space-separated property-table fields — the group-by choices offered by ifc-browser, or the rows shown by feature-inspector. Hierarchy columns render as expandable TREES and are offered automatically when the model has them: \"spatialPath\" (site → storey), \"typePath\", \"systemPath\", \"classificationPath\"."
        },
        {
          "name": "scale-fields",
          "description": "ifc-browser: space-separated NUMERIC fields offered as graduated colour ramps alongside the categorical ones."
        },
        {
          "name": "rows",
          "description": "ifc-browser: visible rows before the value list scrolls (default 6)."
        },
        {
          "name": "no-color",
          "description": "ifc-browser: hide the colour-mode select and leave the model in its own IFC surface colours."
        },
        {
          "name": "show-non-physical",
          "description": "ifc-browser: include non-physical classes (IfcSpace, IfcOpeningElement, …) in the value list, which are hidden by default."
        },
        {
          "name": "placeholder",
          "description": "feature-inspector: text shown when nothing is selected."
        },
        {
          "name": "no-outlines",
          "description": "ifc-loader: skip the companion outline PathLayer for the models it loads."
        },
        {
          "name": "layers",
          "description": "ifc-clash: the two co-registered model layer ids to compare, e.g. \"arch mep\"."
        },
        {
          "name": "tolerance",
          "description": "ifc-clash: metres of real interpenetration required before a pair counts (default 0). Raise it to ignore modelling noise."
        },
        {
          "name": "wasm-path",
          "description": "ifc-loader: serve web-ifc from your own origin instead of unpkg — required for offline, air-gapped or strict-CSP deployments. Vendor the files with `npm run vendor:web-ifc <dir>` first."
        },
        {
          "name": "federate",
          "description": "ifc-loader: accept SEVERAL models into one co-registered scene (one drop zone, one layer per model, each with its own visibility toggle) instead of replacing the previous one."
        },
        {
          "name": "independent",
          "description": "ifc-loader: do NOT share the map’s model-space origin — for pages loading unrelated models rather than disciplines of one building."
        },
        {
          "name": "outline-color",
          "description": "ifc-loader: colour for the outline overlay it builds, e.g. \"[38, 46, 58, 200]\"."
        },
        {
          "name": "ghost-opacity",
          "description": "ifc-loader: ghost fade for the mesh layer it builds (default 0.15)."
        },
        {
          "name": "title",
          "description": "Widget heading."
        }
      ],
      "references": [
        {
          "name": "Testing & widgets",
          "url": "https://github.com/NikaGeospatial/onlymapjs/blob/main/docs/testing.md"
        }
      ]
    },
    {
      "name": "om-story",
      "description": "A guided tour: time → action. Steps reference layers/overlays by id — never contain them.",
      "attributes": [
        {
          "name": "id",
          "description": "Story id — referenced by the player widget and story-* actions."
        },
        {
          "name": "warm-tiles",
          "description": "Pre-load every 3D tileset along this story's camera route in the background as soon as the story connects — flyby pop-in / LOD refinement blur becomes a sub-frame re-upload. Completion announced via the om-tiles-warmed event on <om-map>."
        },
        {
          "name": "paced",
          "description": "Load-paced playback: the story steps its own clock frame by frame (optionally paced=\"60\" story-fps, default 30), owns the camera along the fly-to route, and never advances while a 3D tileset is still refining — no frame ever shows unrefined tiles. Wall-clock stretches; emits om-paced-tick {t, waitedMs} per frame. Composes with warm-tiles (warm first → far shorter waits)."
        },
        {
          "name": "paced-max-hold",
          "description": "Per-frame tile-wait cap for paced playback (duration grammar, default 10s): a frame still waiting past the cap advances anyway, so a dead tile server degrades to ordinary pop-in instead of freezing the story. Heavy tilesets (Google Photorealistic 3D Tiles) can be tile-bound longer than 10s per frame — raise it (e.g. \"30s\"), or set \"none\" to wait unconditionally for full refinement (guaranteed-sharp recorded takes; only pause can then unstick a dead server)."
        },
        {
          "name": "autoplay",
          "description": "Start after om-map-ready."
        },
        {
          "name": "loop",
          "description": "Restart when the tour ends."
        },
        {
          "name": "interrupt",
          "description": "What user camera gestures do to playback.",
          "values": [
            {
              "name": "pause"
            },
            {
              "name": "ignore"
            }
          ]
        }
      ],
      "references": [
        {
          "name": "Map stories",
          "url": "https://github.com/NikaGeospatial/onlymapjs/blob/main/docs/stories.md"
        }
      ]
    },
    {
      "name": "om-step",
      "description": "One story step: action=\"…\" plus payload attributes, or a bare effect verb (trace / pulse / fade / populate).",
      "attributes": [
        {
          "name": "action",
          "description": "Action to dispatch at this step's time.",
          "values": [
            {
              "name": "toggle-layer"
            },
            {
              "name": "zoom-in"
            },
            {
              "name": "zoom-out"
            },
            {
              "name": "filter-layer"
            },
            {
              "name": "highlight-feature"
            },
            {
              "name": "fade"
            },
            {
              "name": "pulse"
            },
            {
              "name": "populate"
            },
            {
              "name": "trace"
            },
            {
              "name": "story-play"
            },
            {
              "name": "story-pause"
            },
            {
              "name": "story-seek"
            },
            {
              "name": "fly-to"
            },
            {
              "name": "zoom-to-feature"
            },
            {
              "name": "show-overlay"
            },
            {
              "name": "hide-overlay"
            },
            {
              "name": "show-tooltip"
            },
            {
              "name": "hide-tooltip"
            },
            {
              "name": "draw-mode"
            },
            {
              "name": "draw-commit"
            },
            {
              "name": "draw-cancel"
            },
            {
              "name": "draw-delete"
            },
            {
              "name": "draw-clear"
            },
            {
              "name": "draw-config"
            },
            {
              "name": "draw-save"
            },
            {
              "name": "export-region-3d"
            },
            {
              "name": "measure-mode"
            },
            {
              "name": "measure-clear"
            },
            {
              "name": "measure-units"
            },
            {
              "name": "set-basemap"
            },
            {
              "name": "set-lighting"
            },
            {
              "name": "set-terrain"
            },
            {
              "name": "set-clip-box"
            },
            {
              "name": "clip-box-edit"
            },
            {
              "name": "set-widgets-visible"
            },
            {
              "name": "undo"
            },
            {
              "name": "redo"
            },
            {
              "name": "warm-tiles"
            }
          ]
        },
        {
          "name": "duration",
          "description": "How long the step's animation runs (\"3s\", \"800ms\"); also passed to the action."
        },
        {
          "name": "delay",
          "description": "Stagger before the step starts."
        },
        {
          "name": "follow",
          "description": "trace steps: lock the camera to the line's drawing tip for the step's duration (the travel-map move)."
        },
        {
          "name": "easing",
          "description": "trace steps: clock curve for the draw.",
          "values": [
            {
              "name": "linear"
            },
            {
              "name": "ease-in"
            },
            {
              "name": "ease-out"
            },
            {
              "name": "ease-in-out"
            }
          ]
        },
        {
          "name": "parallel",
          "description": "Start with the previous step instead of after everything before it."
        },
        {
          "name": "trace",
          "description": "Effect verb: progressive draw (whole TripsLayer, or one feature with feature-id)."
        },
        {
          "name": "pulse",
          "description": "Effect verb: attention oscillation."
        },
        {
          "name": "fade",
          "description": "Effect verb: animate opacity to `to` over duration."
        },
        {
          "name": "populate",
          "description": "Effect verb: rows drop in one by one (GPU filter sweep)."
        },
        {
          "name": "layer",
          "description": "Target layer id."
        },
        {
          "name": "target",
          "description": "Target overlay id (show/hide-overlay)."
        },
        {
          "name": "feature-id",
          "description": "Target feature id (highlight/zoom/trace)."
        },
        {
          "name": "center",
          "description": "Camera center \"[lng, lat]\" (fly-to)."
        },
        {
          "name": "zoom",
          "description": "Camera zoom (fly-to)."
        },
        {
          "name": "pitch",
          "description": "Camera pitch in degrees (fly-to)."
        },
        {
          "name": "bearing",
          "description": "Camera bearing in degrees (fly-to)."
        },
        {
          "name": "curve",
          "description": "Arced flight path instead of a linear ease (fly-to)."
        }
      ],
      "references": [
        {
          "name": "Map stories",
          "url": "https://github.com/NikaGeospatial/onlymapjs/blob/main/docs/stories.md"
        }
      ]
    }
  ]
}
