Files
TREK/shared/src/plugins/plugin-poi-facts.ts
T
Maurice 1727732841 feat(plugins): plugins can add POI categories to the map and answer them
A new manifest capability poiCategories (up to 4, icon from an allow-list,
strict #rrggbb color) and the hook poiCategoryProvider.getPois behind the
hook:poi-category-provider permission. GET /api/plugin-pois in the plugin
contributions module answers them in the /api/maps/pois shape, with
search_plugin_pois as the MCP twin. plugin: ids no longer count as Google
place ids. SDK 1.8.0 carries the types, validation and docs.

On the map, one hook merges the built-in categories with the ones active
plugins declare, and the pill shows the plugin chips after a divider on
desktop and phone, scrolling sideways instead of shrinking a chip below
its touch target. A plugin chip searches through a repo that refuses
offline and parses the answer strictly. Its pins, on Leaflet and GL, use
the category's own icon and color, both checked again before they reach
any markup, and the hover card lists the plugin's details as escaped
text. A plugin POI can be added as a place like any other. The admin
panels on desktop and phone show a chip for the new permission and the
categories a plugin would add, from one shared module.

Addresses discussion #1781.
2026-09-25 01:24:55 +00:00

50 lines
1.6 KiB
TypeScript

/**
* The fixed facts behind a plugin POI category (#1781): which icons one may use and
* how many a plugin may declare.
*
* A file of plain constants with no imports on purpose. Besides the contract in
* plugin-poi.schema.ts, server/scripts/gen-plugin-facts.ts reads it and writes the
* same values into plugin-sdk/src/generated/host-facts.ts, so `trek-plugin validate`
* checks a manifest against the list the host enforces. That script runs in a CI job
* with only the server installed, which is why nothing here may pull in zod.
*/
/**
* Lucide icon names a plugin POI category may carry.
*
* A closed list rather than any lucide name, for two reasons. The pill and the
* marker builders resolve the name to a component or an SVG, and a closed list means
* a plugin can never make the host import something it did not plan to ship. And the
* choice is small on purpose: these are the shapes the use cases need (trails and
* trailheads, charging, accessibility, water and toilets, camping, community places).
* Lucide 0.344 has no toilet glyph, so Bath stands in for that one.
*/
export const PLUGIN_POI_ICONS = [
'Footprints',
'Mountain',
'MountainSnow',
'Signpost',
'Trees',
'TentTree',
'Tent',
'Accessibility',
'Droplet',
'Droplets',
'PlugZap',
'Zap',
'Bath',
'Bike',
'Waves',
'Landmark',
'MapPin',
'Star',
'Heart',
'Info',
] as const;
/** How many POI categories one plugin may add to the explore pill. */
export const PLUGIN_POI_MAX_CATEGORIES = 4;
/** Longest category label, in the fallback and in every per-language entry. */
export const PLUGIN_POI_LABEL_MAX = 40;