SemanticTreeLegend says a dot is a locality, on every map with people-group pins

The Driver's card BUILD-APPROXIMATE-PIN-NOTICE: every map that shows people-group pins must say so plainly.
The standing APPROXPIN note existed only under LegendRows and in the pin card, so maps whose legend is
SemanticTreeLegend (the prayer map's flat tabs among them) never showed it (rega, row 46).

It now renders under the tree when the map's own data holds named Point features (the injected dataStore);
maps without people-group pins show nothing. A pinNote prop overrides for a leaf that already says it.
This commit is contained in:
Doxa Maps 2026-09-26 18:49:02 +00:00
parent 8ec207c662
commit 0d0ee3cbed

View file

@ -23,6 +23,7 @@ import { useOptionalI18n } from '@map/composables/useOptionalT.js'
import { useShadowStyles } from '../../composables/useShadowStyles.js'
import { useInstance } from '../../composables/usePplrInstance.js'
import LegendProgressBar from './LegendProgressBar.vue'
import ApproxPinNote from './ApproxPinNote.vue'
// .stl-export-backdrop is an invisible click-catcher ("captures the next click"), so when it is
// clipped nothing LOOKS wrong — but inside the cap-5 shell contain:layout on .vtl-content limits
// it to the content pane (measured 1024x793 @ (256,107) at 1280x900), so a click on the rail or
@ -79,6 +80,10 @@ function tabInfo(tab) {
const props = defineProps({
nodes: { type: Array, default: () => [] },
// APPROXPIN standing note (Driver card BUILD-APPROXIMATE-PIN-NOTICE: every map that shows people-group
// pins says plainly that a dot is a locality). null = decide from the map's own data: shown when the
// injected dataStore holds named Point features. true/false overrides, for a leaf that already says it.
pinNote: { type: Boolean, default: null },
tabs: { type: Array, default: null },
// WHICH GENERATION THE LEGEND OPENS ON. Index into `tabs`; 0 (the top of the
// tree) is the default, which is what every existing profile already gets.
@ -120,6 +125,17 @@ const progressData = computed(() => props.progress ?? unref(injectedProgress) ??
// on the desktop title bar, the mobile sheet title and the collapsed reopen pill.
const displayTitle = computed(() => progressData.value ? t('legend.progress.title') : props.title)
const stlIsDark = computed(() => (instance?.theme.value || 'dark') === 'dark')
const pinDataStore = inject('dataStore', null)
const showPinNote = computed(() => {
if (props.pinNote !== null) return props.pinNote
const sources = pinDataStore?.sources || {}
for (const id in sources) {
const f = sources[id]?.features?.[0]
const p = f?.properties || {}
if (f?.geometry?.type === 'Point' && (p.name || p.peopleName || p.PeopNameInCountry)) return true
}
return false
})
// A click on a bar span selects the matching legend row through the SAME handler
// the row uses (selectNode → emit('select') → the profile's filter/camera path).
function findNodeById(nodes, id) {
@ -1328,6 +1344,7 @@ useShadowStyles(`
<span class="stl-overflow-hint">{{ T('legend.useGeocoderHint', 'use the geocoder above to find the rest') }}</span>
</div>
</div>
<ApproxPinNote v-if="showPinNote" :dark="stlIsDark" />
</div>
</div>