Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 24 additions & 16 deletions demo/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,42 +26,52 @@ import searchPlugin from '/plugins/search/src/index.js'
import createInteractPlugin from '/plugins/interact/src/index.js'
import createFramePlugin from '/plugins/beta/frame/src/index.js'

const pointData = {type: 'FeatureCollection',features: [{type: 'Feature',properties: {category:'prehistoric'},geometry: {coordinates: [-2.4558622,54.5617135],type: 'Point'}},{type: 'Feature',properties: {category:'roman'},geometry: {coordinates: [-2.439823,54.5525437],type: 'Point'}},{type: 'Feature',properties: {category:'medieval'},geometry: {coordinates: [-2.4481939,54.5575261],type: 'Point'}}]}
const pointData = {type: 'FeatureCollection',features: [{type: 'Feature',properties: { category:'prehistoric', name: 'Prehistoric feature' }, geometry: { coordinates: [-2.4558622,54.5617135], type: 'Point' }},{ type: 'Feature', properties: { category: 'roman', name: 'Roman feature' }, geometry: { coordinates: [-2.439823,54.5525437], type: 'Point' }},{ type: 'Feature', properties: { category:'medieval', name: 'Medieval feature' }, geometry: { coordinates: [-2.4481939,54.5575261], type: 'Point'} }]}

const interactPlugin = createInteractPlugin({
layers: [{
layerId: 'historic-monuments-prehistoric-symbol',
// labelProperty: 'name'
// idProperty: 'gid'
},{
layerId: 'land-covers-110',
// labelProperty: 'gid'
// idProperty: 'gid'
},{
layerId: 'land-covers-130-131',
// labelProperty: 'gid'
// idProperty: 'gid'
},{
layerId: 'land-covers-332',
// labelProperty: 'gid'
// idProperty: 'gid'
},{
layerId: 'land-covers-379',
// labelProperty: 'gid'
// idProperty: 'gid'
},{
layerId: 'land-covers-other',
// labelProperty: 'gid'
// idProperty: 'gid'
},{
layerId: 'OS/TopographicArea_1/Agricultural Land',
idProperty: 'TOID'
},{
layerId: 'hedge-control',
idProperty: 'id'
},{
},
// {
// layerId: 'hedge-control',
// idProperty: 'id'
// },
// {
// layerId: 'OS/TopographicArea_1/Agricultural Land',
// idProperty: 'TOID'
// },
{
layerId: 'fill-inactive.cold',
idProperty: 'id'
// idProperty: 'id'
},{
layerId: 'stroke-inactive.cold',
idProperty: 'id'
}],
// idProperty: 'id'
}
],
debug: true,
interactionModes: ['selectMarker', 'placeMarker', 'selectFeature'], // e.g. ['selectMarker'], ['selectFeature'], ['placeMarker'], or combinations
interactionModes: ['selectMarker', 'selectFeature'], // e.g. ['selectMarker'], ['selectFeature'], ['placeMarker'], or combinations
multiSelect: true,
deselectOnClickOutside: true
})
Expand Down Expand Up @@ -304,10 +314,8 @@ interactiveMap.on('map:ready', function (e) {
// aspectRatio: 1
// })
interactPlugin.enable()
interactiveMap.addMarker('my-marker-1', [-2.4555608,54.5655407], { showLabel: true, label: 'My label' })
interactiveMap.addMarker('my-marker-2', [-2.4511636,54.5638338], {
symbol: 'square'
})
interactiveMap.addMarker('my-marker-1', [-2.4555608,54.5655407], { label: 'My label', showLabel: true })
interactiveMap.addMarker('my-marker-2', [-2.4511636,54.5638338], { label: 'Another marker', symbol: 'square' })
})

interactiveMap.on('datasets:ready', function () {
Expand Down
2 changes: 0 additions & 2 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,6 @@ App-wide defaults for symbol and marker appearance.
| `symbol` | `'pin'` |
| `backgroundColor` | `'#ca3535'` |
| `foregroundColor` | `'#ffffff'` |
| `haloWidth` | `'1'` |
| `selectedWidth` | `'6'` |

```js
new InteractiveMap('map', {
Expand Down
13 changes: 11 additions & 2 deletions docs/api/map-style-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Colour scheme for the app UI chrome — panels, buttons, and controls. Set to `'
### `mapColorScheme`
**Type:** `'light' | 'dark'`

Colour scheme for elements rendered on top of the map. Sets the default values of `haloColor`, `selectedColor`, and `foregroundColor` when those are not explicitly provided. Set to `'dark'` when the basemap is dark (e.g. night or aerial) so that overlays remain legible against it.
Colour scheme for elements rendered on top of the map. Sets the default values of `haloColor`, `selectedColor`, `activeColor`, and `foregroundColor` when those are not explicitly provided. Set to `'dark'` when the basemap is dark (e.g. night or aerial) so that overlays remain legible against it.

- `'light'` (default) — dark overlays (`#0b0c0c`) on a light basemap, white halo
- `'dark'` — light overlays (`#ffffff`) on a dark or aerial basemap, dark halo
Expand Down Expand Up @@ -92,12 +92,21 @@ Falls back to the `mapColorScheme` default when not set (`#ffffff` for light, `#
### `selectedColor`
**Type:** `string`

Theme colour for selected state — used by map overlay components to indicate a selected feature.
Theme colour for committed selection — used by map overlay components to indicate a selected feature.

Falls back to the `mapColorScheme` default when not set (`#0b0c0c` for light, `#ffffff` for dark). Injected as the `--map-overlay-selected-color` CSS custom property.

---

### `activeColor`
**Type:** `string`

Theme colour for the active (keyboard cursor) focus ring — shown on the item currently under the keyboard cursor, whether or not it is committed to the selection.

Falls back to `#ffdd00` (GOV.UK yellow) for both light and dark schemes when not set.

---

### `foregroundColor`
**Type:** `string`

Expand Down
14 changes: 7 additions & 7 deletions docs/api/marker-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ Inner SVG path content (no `<svg>` wrapper) to render instead of a registered sy
// Using built-in tokens with per-style colours
markers.add('id', coords, {
symbolSvgContent: `
<path d="..." fill="none" stroke="{{selectedColor}}" stroke-width="{{selectedWidth}}"/>
<path d="..." fill="{{backgroundColor}}" stroke="{{haloColor}}" stroke-width="{{haloWidth}}"/>
<path d="..." fill="{{selectedColor}}" stroke="{{activeColor}}" stroke-width="6" paint-order="stroke fill"/>
<path d="..." fill="{{backgroundColor}}" stroke="{{haloColor}}" stroke-width="2" paint-order="stroke fill"/>
<path d="..." fill="{{foregroundColor}}"/>
`,
viewBox: '0 0 38 38',
viewBox: '0 0 44 44',
anchor: [0.5, 1],
backgroundColor: { outdoor: '#d4351c', dark: '#ff6b6b' }
})
Expand All @@ -72,16 +72,16 @@ markers.add('id', coords, {
})
```

`{{selectedColor}}` and `{{selectedWidth}}` are required to render the selected ring around the marker when it is in its selected state.
`{{selectedColor}}` and `{{activeColor}}` are required to render the selection and focus rings.

> [!NOTE]
> `selectedColor` cannot be set per marker — it is controlled by `MapStyleConfig.selectedColor`.
> `selectedColor` and `activeColor` cannot be set per marker — they are controlled by `MapStyleConfig`.

---

### `viewBox`
**Type:** `string`
**Default:** registered symbol's viewBox, or `'0 0 38 38'`
**Default:** registered symbol's viewBox, or `'0 0 44 44'`

SVG `viewBox` attribute for the symbol. Use alongside `symbolSvgContent` when your paths use a different coordinate space.

Expand Down Expand Up @@ -133,6 +133,6 @@ Whether to render a visible label bubble above the marker symbol. When `false`,

### Colour and graphic properties

`backgroundColor`, `foregroundColor`, `haloWidth`, `graphic`, `selectedWidth`, and any custom tokens are all supported.
`backgroundColor`, `foregroundColor`, `graphic`, and any custom tokens are all supported.

See [Symbol Config](./symbol-config.md) for the full property reference.
36 changes: 10 additions & 26 deletions docs/api/symbol-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Symbol properties control the appearance of markers and point dataset features.

Each property is optional. A value set directly on a marker or dataset layer takes priority over everything else. If a property is not set there, the value registered with the symbol is used. If the symbol has no value for that property, the app-wide `symbolDefaults` from the constructor applies. If none of those are set, the built-in fallback listed under each property below is used.

`haloColor`, `selectedColor`, `haloWidth`, and `selectedWidth` are required tokens in the SVG structure (see [SVG structure](#svg-structure)). Include them in any custom `symbolSvgContent` — the app resolves their values automatically. Note that `haloColor` and `selectedColor` are always derived from the active map style and cannot be configured.
`haloColor`, `selectedColor`, and `activeColor` are required tokens in the SVG structure (see [SVG structure](#svg-structure)). Include them in any custom `symbolSvgContent` — the app resolves their values automatically. All three are derived from the active map style — configure them via `MapStyleConfig`, not per symbol or marker.

## Style-keyed colours

Expand Down Expand Up @@ -37,11 +37,11 @@ Inner SVG path content (no `<svg>` wrapper) to render as the symbol. Use `{{toke
```js
{
symbolSvgContent: `
<path d="..." fill="none" stroke="{{selectedColor}}" stroke-width="{{selectedWidth}}"/>
<path d="..." fill="{{backgroundColor}}" stroke="{{haloColor}}" stroke-width="{{haloWidth}}"/>
<path d="..." fill="{{selectedColor}}" stroke="{{activeColor}}" stroke-width="6" paint-order="stroke fill"/>
<path d="..." fill="{{backgroundColor}}" stroke="{{haloColor}}" stroke-width="2" paint-order="stroke fill"/>
<path d="..." fill="{{foregroundColor}}"/>
`,
viewBox: '0 0 38 38',
viewBox: '0 0 44 44',
anchor: [0.5, 1]
}
```
Expand All @@ -52,7 +52,7 @@ See [SVG structure](#svg-structure) for the standard three-layer pattern.

### `viewBox`
**Type:** `string`
**Default:** registered symbol's viewBox, or `'0 0 38 38'`
**Default:** registered symbol's viewBox, or `'0 0 44 44'`

SVG `viewBox` attribute. Use alongside `symbolSvgContent` when your paths use a different coordinate space.

Expand Down Expand Up @@ -87,22 +87,6 @@ Foreground fill colour — the inner graphic element (e.g. the dot inside a pin)

---

### `haloWidth`
**Type:** `number`
**Default:** `1`

Stroke width of the halo around the symbol background shape. Can be set in constructor `symbolDefaults`, at symbol registration, or per marker/dataset layer.

---

### `selectedWidth`
**Type:** `number`
**Default:** `6`

Stroke width of the selection ring shown when a marker is selected. Can be set in constructor `symbolDefaults` or per marker/dataset layer.

---

### `graphic`
**Type:** `string`

Expand Down Expand Up @@ -147,14 +131,14 @@ Symbols are defined as inner SVG path content (no `<svg>` wrapper) using `{{toke

```js
svg: `
<path d="..." fill="none" stroke="{{selectedColor}}" stroke-width="{{selectedWidth}}"/>
<path d="..." fill="{{backgroundColor}}" stroke="{{haloColor}}" stroke-width="{{haloWidth}}"/>
<path d="..." fill="{{selectedColor}}" stroke="{{activeColor}}" stroke-width="6" paint-order="stroke fill"/>
<path d="..." fill="{{backgroundColor}}" stroke="{{haloColor}}" stroke-width="2" paint-order="stroke fill"/>
<path d="..." fill="{{foregroundColor}}"/>
`
```

- **Layer 1** — selection ring (stroke only, fill none) — hidden in normal rendering, visible when selected
- **Layer 2** — background shape with halo stroke
- **Layer 1** — ring layer: `fill` is the selected ring (`{{selectedColor}}`), `stroke` is the active ring (`{{activeColor}}`). Both hidden in normal rendering. `paint-order="stroke fill"` ensures the stroke extends outward without clipping the fill.
- **Layer 2** — background shape with fixed halo stroke
- **Layer 3** — foreground graphic (e.g. inner dot)

> `{{haloColor}}` and `{{selectedColor}}` are always injected from the active map style. They must be present in the SVG but cannot be configured.
> `{{haloColor}}`, `{{selectedColor}}`, and `{{activeColor}}` are always injected from the active map style. They must be present in the SVG but cannot be configured per symbol or marker.
41 changes: 28 additions & 13 deletions docs/api/symbol-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ The symbol registry is a service that manages reusable named symbols for map mar

## Built-in symbols

Two symbols are registered by default:
Three symbols are registered by default:

| ID | Anchor | Description |
|----|--------|-------------|
| `'pin'` | `[0.5, 1]` | Teardrop pin — tip aligns with the coordinate |
| `'circle'` | `[0.5, 0.5]` | Filled circle — centre aligns with the coordinate |
| `'square'` | `[0.5, 0.5]` | Rounded square — centre aligns with the coordinate |

Both use the standard `{{token}}` placeholders and respect the resolution order described in [Symbol Config](./symbol-config.md#how-values-are-resolved).

Expand All @@ -33,7 +34,7 @@ Returns the merged app-wide defaults (hardcoded `symbolDefaults.js` + constructo

```js
const defaults = services.symbolRegistry.getDefaults()
// { symbol: 'pin', backgroundColor: '#ca3535', selectedColor: { outdoor: '#0b0c0c', dark: '#ffffff' }, ... }
// { symbol: 'pin', backgroundColor: '#ca3535', foregroundColor: '#ffffff', ... }
```

---
Expand All @@ -46,19 +47,19 @@ Register a custom symbol. Once registered it can be referenced by ID via `Marker
|----------|------|----------|-------------|
| `id` | `string` | Yes | Unique symbol identifier |
| `svg` | `string` | Yes | Inner SVG path content with `{{token}}` placeholders — see [SVG structure](./symbol-config.md#svg-structure) |
| `viewBox` | `string` | Yes | SVG viewBox, e.g. `'0 0 38 38'` |
| `viewBox` | `string` | Yes | SVG viewBox, e.g. `'0 0 44 44'` |
| `anchor` | `[number, number]` | Yes | Normalised [x, y] anchor point |
| *(token)* | `string \| Record<string, string>` | No | Default token value for this symbol, e.g. `backgroundColor: '#1d70b8'`. `selectedColor` and `selectedWidth` are ignored here — set them via constructor `symbolDefaults`. |
| *(token)* | `string \| Record<string, string>` | No | Default token value for this symbol, e.g. `backgroundColor: '#1d70b8'`. `selectedColor` and `activeColor` are ignored here — they are always derived from the active map style. |

```js
services.symbolRegistry.register({
id: 'star',
viewBox: '0 0 38 38',
viewBox: '0 0 44 44',
anchor: [0.5, 0.5],
backgroundColor: '#1d70b8',
svg: `
<path d="..." fill="none" stroke="{{selectedColor}}" stroke-width="{{selectedWidth}}"/>
<path d="..." fill="{{backgroundColor}}" stroke="{{haloColor}}" stroke-width="{{haloWidth}}"/>
<path d="..." fill="{{selectedColor}}" stroke="{{activeColor}}" stroke-width="6" paint-order="stroke fill"/>
<path d="..." fill="{{backgroundColor}}" stroke="{{haloColor}}" stroke-width="2" paint-order="stroke fill"/>
<path d="..." fill="{{foregroundColor}}"/>
`
})
Expand Down Expand Up @@ -88,28 +89,42 @@ const symbols = services.symbolRegistry.list()

---

### `resolve(symbolDef, styleColors, mapStyleId)`
### `resolve(symbolDef, styleColors, mapStyle)`

Resolves a symbol's SVG for **normal (unselected) rendering**. The `{{selectedColor}}` token is always replaced with an empty string — the selection ring is structurally present but invisible.
Resolves a symbol's SVG for **normal (unselected, inactive) rendering**. Both `{{selectedColor}}` and `{{activeColor}}` are replaced with `'none'`, so neither ring is visible.

```js
const svg = services.symbolRegistry.resolve(
services.symbolRegistry.get('pin'),
{ backgroundColor: '#d4351c' },
'outdoor'
mapStyle
)
```

---

### `resolveSelected(symbolDef, styleColors, mapStyleId)`
### `resolveActive(symbolDef, styleColors, mapStyle)`

Resolves a symbol's SVG for **selected rendering**. The `{{selectedColor}}` token uses the cascade value. Use this when rendering the highlight layer for an interact or datasets selection.
Resolves a symbol's SVG for **active (keyboard cursor) rendering**. Both `{{selectedColor}}` and `{{activeColor}}` are live — the committed ring and the focus ring are both visible simultaneously, so an active item always shows both rings regardless of whether it is also selected.

```js
const svg = services.symbolRegistry.resolveActive(
services.symbolRegistry.get('pin'),
{ backgroundColor: '#d4351c' },
mapStyle
)
```

---

### `resolveSelected(symbolDef, styleColors, mapStyle)`

Resolves a symbol's SVG for **committed-selection rendering**. `{{selectedColor}}` is live (the black committed ring is visible) but `{{activeColor}}` is forced to `'none'` — use this when an item is selected but not the current keyboard cursor.

```js
const svg = services.symbolRegistry.resolveSelected(
services.symbolRegistry.get('pin'),
{ backgroundColor: '#d4351c' },
'outdoor'
mapStyle
)
```
2 changes: 2 additions & 0 deletions docs/plugins/interact.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,11 @@ layers: [
|----------|------|-------------|
| `layerId` | `string` | **Required.** The map layer identifier to enable selection on |
| `idProperty` | `string` | Property name used as the feature's unique identifier. If omitted, features are matched by index |
| `labelProperty` | `string` | Property name used as the feature's display label in the keyboard-accessible listbox. **Required for features to appear in keyboard navigation** |
| `selectedStroke` | `string` | Overrides the selection stroke colour for this layer. Defaults to `MapStyleConfig.selectedColor` |
| `selectedFill` | `string` | Overrides the selection fill colour for this layer. Defaults to `transparent` |
| `selectedStrokeWidth` | `number` | Overrides the selection stroke width for this layer. Defaults to `3` |
| `activeStroke` | `string` | Overrides the keyboard cursor ring colour for this layer. Defaults to `MapStyleConfig.activeColor` |

#### Finding layer IDs

Expand Down
4 changes: 2 additions & 2 deletions plugins/beta/datasets/src/components/svgProperties.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const SVG_SIZE = 20
export const SVG_SIZE = 20 // Width and height attributes of the svg element
export const SVG_CENTER = SVG_SIZE / 2
const SVG_SYMBOL_SIZE = 38
const SVG_SYMBOL_SIZE = 44 // Width and height attributes of the svg element if its a marker or point feature symbol

export const svgProps = {
xmlns: 'http://www.w3.org/2000/svg',
Expand Down
4 changes: 2 additions & 2 deletions plugins/beta/datasets/src/panels/Key.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@
.am-c-datasets-key-symbol {
position: relative;
flex-shrink: 0;
margin: 0 13px 0 2px;
margin: 0 13px 0 3px;
}

.am-c-datasets-key-symbol--point {
margin: -9px 3px -9px -7px;
margin: -12px 1px -12px -9px;
}
Loading
Loading