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
2 changes: 1 addition & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Full agent context is in [`AGENTS.md`](../AGENTS.md) at the repo root. Read that

## GitHub Copilot — additional notes

- `npm test` runs unit tests only (vitest, <1 s). E2E tests run separately via `npm run test:e2e`. Unit tests are the standard final-check before confirming a task done.
- When creating tests that capture screenshots, always use the full viewport (`page.screenshot()` without `fullPage` — the app fills the viewport by design).
- Prefer `expect.poll()` over `waitForTimeout` for async side-effects in tests.
- The demo app uses `id: "app"`, so the localStorage view key in tests is `navigator_view_app`.

63 changes: 35 additions & 28 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ npm run build # build the library for distribution
npm run test:unit # run vitest unit tests (<1 s)
npm run test:e2e -- tests/e2e/{spec}.spec.js # run only the relevant E2E spec
npm run test:e2e # run all E2E tests
npm test # run all tests: unit + E2E (final check before confirming a task done)
npm test # run unit tests only (final check before confirming a task done)
```

### Running tests — timing guidance

- A single spec takes **15–45 seconds**.
- The full suite (`npm test`) takes **2–3 minutes**.
`npm test` runs unit tests only and completes in under a second.

When running tests with a shell tool, use `mode="sync"` with `initial_wait` set to at least **60** for a single spec and **240** for the full suite. You will be automatically notified when the command completes — **do not poll repeatedly with short waits**. Wait for the completion notification, then read the output once.
E2E tests are available separately via `npm run test:e2e` but are slow (a single spec takes **15–45 seconds**, the full suite **2–3 minutes**) and are not required as part of the standard task completion check. Run E2E tests manually when validating browser integration or complex user flows.

When running E2E tests with a shell tool, use `mode="sync"` with `initial_wait` set to at least **60** for a single spec and **240** for the full suite. You will be automatically notified when the command completes — **do not poll repeatedly with short waits**. Wait for the completion notification, then read the output once.

---

Expand All @@ -52,6 +53,7 @@ src/
useLocale.js # i18n: language resolution, translations
useSettings.js # user preferences: theme, units, language
useLocate.js # GPS locate feature
useGeoJSON.js # GeoJSON rendering: points, lines, polygons
components/
panels/
about.vue # About panel
Expand Down Expand Up @@ -92,11 +94,13 @@ Logic lives in composables, not components. Per-instance state is cached in a mo
const cache = new Map();

export const useMyFeature = () => {
const instanceId = inject('navigatorId', 'navigator');
const instanceId = inject("navigatorId", "navigator");

if (!cache.has(instanceId)) {
cache.set(instanceId, {
state: useStorage('my-feature', { /* defaults */ }),
state: useStorage("my-feature", {
/* defaults */
}),
});
}

Expand All @@ -107,6 +111,7 @@ export const useMyFeature = () => {
### CSS selectors

Core elements use classes, not ids, to avoid collisions in multi-instance setups:

- `.navigator-map` — MapLibre container
- `.navigator-top` — top navigation bar
- `.navigator-panel` — Bootstrap offcanvas side panel
Expand All @@ -122,7 +127,7 @@ lat: 50.6539, lng: -128.0094 // Scarlet Ibis Pub, Holberg, British Columbia, C
In MapLibre `center` arrays (which are `[lng, lat]`):

```js
center: [-128.0094, 50.6539]
center: [-128.0094, 50.6539];
```

### Features
Expand All @@ -140,34 +145,35 @@ Documentation is split into two directories:

Core docs:

| Doc | Purpose |
|-----|---------|
| `docs/core/1.config.md` | `Navigator.create()` config API reference |
| `docs/core/2.instances.md` | Multi-instance setup, storage convention, architecture |
| `docs/core/3.map.md` | `useMap` full API: map lifecycle, view persistence, URL hash |
| `docs/core/4.ui.md` | `useUI` full API: responsive breakpoints, panel, navigation |
| `docs/core/5.locale.md` | Locale API, translations, OSM multilingual names |
| `docs/core/6.theme.md` | Bootstrap SCSS theme architecture |
| `docs/core/7.testing.md` | Testing conventions and screenshot strategy |
| Doc | Purpose |
| -------------------------- | ------------------------------------------------------------ |
| `docs/core/1.config.md` | `Navigator.create()` config API reference |
| `docs/core/2.instances.md` | Multi-instance setup, storage convention, architecture |
| `docs/core/3.map.md` | `useMap` full API: map lifecycle, view persistence, URL hash |
| `docs/core/4.ui.md` | `useUI` full API: responsive breakpoints, panel, navigation |
| `docs/core/5.geojson.md` | `useGeoJSON` API: rendering GeoJSON features with styles |
| `docs/core/6.locale.md` | Locale API, translations, OSM multilingual names |
| `docs/core/7.theme.md` | Bootstrap SCSS theme architecture |
| `docs/core/8.testing.md` | Testing conventions and screenshot strategy |

Extension docs:

| Doc | Purpose |
|-----|---------|
| `docs/extend/1.events.md` | Event emitter, lifecycle callbacks |
| `docs/extend/2.buttons-panels.md` | Config-driven custom buttons and panels |
| `docs/extend/3.plugins.md` | Plugin system: writing, context, cleanup |
| `docs/extend/4.apis.md` | Accessing map, panel, settings, locale, storage |
| `docs/extend/5.features.md` | Building a complete feature as a plugin |
| `docs/extend/6.theme.md` | Custom themes for library consumers |
| Doc | Purpose |
| --------------------------------- | ----------------------------------------------- |
| `docs/extend/1.events.md` | Event emitter, lifecycle callbacks |
| `docs/extend/2.buttons-panels.md` | Config-driven custom buttons and panels |
| `docs/extend/3.plugins.md` | Plugin system: writing, context, cleanup |
| `docs/extend/4.apis.md` | Accessing map, panel, settings, locale, storage |
| `docs/extend/5.features.md` | Building a complete feature as a plugin |
| `docs/extend/6.theme.md` | Custom themes for library consumers |

---

## Adding a New Feature

1. Create `src/composables/use{FeatureName}.js`, `src/components/panels/{feature-name}.vue`, and `src/components/ui/top/{feature-name}.vue` (see `docs/extend/5.features.md`)
2. Create `tests/e2e/feature-name.spec.js` (or `tests/e2e/features/feature-name.spec.js`)
3. Run `npm test -- tests/e2e/{relevant}.spec.js` during development, then `npm test` as a final check
3. Run `npm run test:e2e -- tests/e2e/{relevant}.spec.js` during development if E2E coverage is needed; run `npm test` as a final unit-test check

---

Expand All @@ -184,8 +190,9 @@ A Playwright MCP server is configured in `.github/mcp.json`. Agents with MCP sup
- `docs/core/2.instances.md` — multi-instance setup, storage convention, architecture
- `docs/core/3.map.md` — `useMap` full API
- `docs/core/4.ui.md` — `useUI` full API
- `docs/core/5.locale.md` — locale API, translations
- `docs/core/6.theme.md` — Bootstrap SCSS theme architecture
- `docs/core/7.testing.md` — testing conventions, screenshot strategy, how to run specific specs
- `docs/core/5.geojson.md` — `useGeoJSON` API: rendering GeoJSON features with styles
- `docs/core/6.locale.md` — locale API, translations
- `docs/core/7.theme.md` — Bootstrap SCSS theme architecture
- `docs/core/8.testing.md` — testing conventions, screenshot strategy, how to run specific specs
- `docs/extend/README.md` — extending Navigator: events, plugins, buttons, panels, theming
- `docs/extend/5.features.md` — how to build a feature
2 changes: 1 addition & 1 deletion BUGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

1/ There is a bug with Chrome desktop for mac (macOS only, is fine on Windows) where the map is not zoomable using the mouse scroll wheel. The app works correctly everywhere else tested, including Chrome mobile. Instead of zooming the map, the entire app gets "pulled" up and down, indicating that the browser is treating the map gesture as a scroll instead of a zoom. Diagnose this issue and implement a fix.

2/ @src/components/ui/top/locate.vue contains an element with id locate-button. However because Navigator support multiple instances, this should be either scoped to the instance or use a class instead of an id.
2/ @src/components/ui/top/locate.vue contains an element with id locate-button. However because Navigator support multiple instances, this should be either scoped to the instance or use a class instead of an id. Find and replace all uses of HTML id attributes.

3/ Modals @src/modals/\*.md do not respect the dark theme and display with a white background and black text. Update the modal styles to be compatible with both light and dark themes.
10 changes: 0 additions & 10 deletions FEEDBACK.md

This file was deleted.

4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ npm run dev
### Test

```bash
npm test -- tests/e2e/{spec}.spec.js
npm test # unit tests (vitest)
npm run test:e2e -- tests/e2e/{spec}.spec.js # single E2E spec
npm run test:e2e # full E2E suite
```

See [docs/core/7.testing.md](docs/core/7.testing.md) for the testing strategy.
Expand Down
8 changes: 8 additions & 0 deletions TASKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,11 @@ We are currently on the git branch called "dev". Use git to create a new branch
- feat: add new feature Y
- docs: update documentation for feature Z
- bump: update dependencies for feature A

2/ Currently the @docs/extend/5.features.md example implements drawing and updating a maplibre Line @docs/extend/feature/recordings.js After implementing the example, I notice that this renders correctly when testing on a desktop browser, but on mobile the line does not render at all. This occurs on multiple mobile browsers. It would appear that data about the track is being collected - distance and duration both have positive values and are incrementing when recording, but no line is drawn.

Instead of just diagnosing this one issue, I want you to create a navigator api for rendering geojson data. I want this to be a thin layer on top of maplibre that abstracts away the details of rendering geojson data (sources and style layers) and provides a simple interface for adding, updating, and removing geojson features. Providing styles for the features should be optional, and if not provided, default styles should be applied. For example line colour could be specified as a geojson "navigator." property on the geojson feature, and if not provided, a default colour. The default colour should be a random bright primary colour variation to help distinguish different features. The API should also provide a way to set the default styles for different geometry types (point, line, polygon) and allow these to be overridden on a per-feature basis using the "navigator." properties.

Backwards compatibility is not required, as the library is in early development - I want to nail the geojson:mablibre rendering API first, then update the existing recording example to use this new API. The API should be documented (I think this should belong in @docs/core/5.geojson.md - change numbered filenames across docs) and include examples of how to use it to render different types of geojson features with custom styles. The implementation should be efficient (i.e. not creating a new source and layer for every feature update, cleaning up old sources and layers when features are removed) and work well on both desktop and mobile browsers.

The geojson api should have full test coverage. Unit tests are currently preferred for efficiency, but if there are any parts of the implementation that are difficult to test with unit tests, you can use e2e tests instead. The tests should cover adding, updating, and removing features, as well as applying custom styles and default styles. You should also include tests for edge cases, such as adding features with invalid geojson or styles.
4 changes: 2 additions & 2 deletions docs/core/1.config.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ Language resolution order:
| `en` | English |
| `fr` | Français |

See [Locale](./5.locale.md) for the full locale API, available languages, and how to contribute a translation.
See [Locale](./6.locale.md) for the full locale API, available languages, and how to contribute a translation.

---

Expand Down Expand Up @@ -152,7 +152,7 @@ Navigator.create({

Custom messages are merged on top of the built-in translations — only the keys you supply are overridden. Any unspecified keys continue to use the built-in values.

See [Locale](./5.locale.md) for the full list of translation keys.
See [Locale](./6.locale.md) for the full list of translation keys.

---

Expand Down
2 changes: 1 addition & 1 deletion docs/core/3.map.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ name:{locale} → name (local) → name:en

The expression is updated reactively whenever the language changes in Settings — no page reload required.

See [Locale — OSM Multilingual Names](./5.locale.md#osm-multilingual-names) for full details.
See [Locale — OSM Multilingual Names](./6.locale.md#osm-multilingual-names) for full details.

---

Expand Down
2 changes: 1 addition & 1 deletion docs/core/4.ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,4 @@ Closes the panel without changing the active tab.

---

[← Map](./3.map.md) | [Locale →](./5.locale.md)
[← Map](./3.map.md) | [GeoJSON →](./5.geojson.md)
Loading
Loading