doxa-maps/library/colors/resource.js
Doxa Maps 370446390f C1b: the resource palette moves to library/colors/, and the local colour globs go with it
Completes C1. Source only; studio rebuilds (rule 5B). Cut on top of C1a because it
depends on that move. Rebuild scope: country-posters, doxa-research-map,
research-dashboard, dashboard-plus-grid, gospel-resources.

resource.js existed as TWO identical plugin-local copies with no library original,
while library composables resolved it through the registry — so the library depended
on a plugin registering a module the library itself documented. Now it lives in
library/colors/ like the other eight, both copies are gone, and src/colors/ holds no
.js in either plugin. The local `registerStrategies(import.meta.glob('./src/colors/*.js'))`
in both index.js files is therefore DELETED: it matched nothing after the move, and a
glob that matches nothing reads as a deliberate override. Their now-unused
registerStrategies imports went with them. That also completes the shepherd's original
C1 instruction, which C1a had to defer for exactly this reason.

★ MY OWN PREDICTION HERE WAS WRONG, and the measurement is the only reason this is
clean. I predicted check:one-palette would FAIL after the move, reasoning that the
dashboards carry 6 of resource's 8 hexes (because 6 are SHARED with affinity-block and
language-family, which they legitimately ship) while the 2 unique ones — #20c997
jesusFilm and #2c3e50 noResources — are absent, and the gate fails a PARTIAL palette.
The gate PASSES: 9 strategies, 18 pairs. Once the module is in library/colors/,
_registry.js bundles it into every consumer, so all 8 hexes are present BY CONSTRUCTION.
I had reasoned about the pre-move bundle and assumed the rebuild would not change it.

That also corrects the diagnosis I gave earlier. simpleresearch was right that there
was no disagreement, but not that the 6 were coincidental substrings in minified
output: they are real hexes, genuinely present, shared across three strategies. The
gate cannot attribute a hex to a strategy — which is a real limitation worth knowing,
just not one that bites here.

Stale comments corrected rather than left to rot: five references across
useLegendData, researchLegendOptions, useWagfRegionsLegendData and my own
wagf-region.js header all claimed these palettes live in a plugin folder. One
parenthetical keeps the old path deliberately, as history.

GATES: check:one-palette PASS 9/18 (baselined 6/12 before C1a). check:library-index
PASS after regenerating the derived menu. check:no-free-identifiers PASS. All six
affected bundles build; their artifacts reverted.
2026-09-26 08:51:39 +00:00

139 lines
3.9 KiB
JavaScript

/**
* Gospel Resources Color Strategy
*
* Colors pins based on available gospel resources.
* DEFAULT: Binary coloring - Green (has ANY resource) / Black (no resources)
* LEGEND COUNTS: Show TOTAL for each resource (can overlap)
*/
export const PROPERTY_KEY = 'resourceType'
/**
* Gospel Resources Colors
* DEFAULT: Binary coloring - Green (has ANY resource) / Black (no resources)
* LEGEND: Show TOTAL count for each resource (INCLUSIVE, can overlap)
*/
export const PALETTE = {
bible: '#3498db', // Blue - Bible available
jesusFilm: '#20c997', // Fisher Green (teal-green) - Jesus Film available
radio: '#9b59b6', // Purple - Radio broadcast available
gospel: '#f39c12', // Orange - Gospel recordings available
audio: '#1abc9c', // Teal - Audio resources available
stories: '#e74c3c', // Red - Stories available
hasResources: '#27ae60', // Green - Has ANY gospel resource (default pin color)
noResources: '#2c3e50' // Dark/Black - No gospel resources
}
export const RESOURCE_COLORS = PALETTE
/** Resource priority order for pin coloring */
export const RESOURCE_PRIORITY = ['bible', 'jesusFilm', 'radio', 'gospel', 'audio', 'stories']
/** Resource display names for legend */
export const NAMES = {
bible: 'Bible',
jesusFilm: 'Jesus Film',
radio: 'Radio',
gospel: 'Gospel',
audio: 'Audio',
stories: 'Stories',
hasResources: 'Has Resources',
noResources: 'No Resources'
}
export const RESOURCE_NAMES = NAMES
/**
* Get CSV column name for a resource key.
*/
export function getCSVColumn(resourceKey) {
const mapping = {
bible: 'Bible',
jesusFilm: 'Jesus',
radio: 'Radio',
gospel: 'Gospel',
audio: 'Audio',
stories: 'Stories'
}
return mapping[resourceKey]
}
/**
* Get color for a feature based on resource availability.
* Binary logic: Green if has ANY resource, Black if none.
*/
export function getColor(properties) {
for (const resourceKey of RESOURCE_PRIORITY) {
const value = properties[resourceKey] || properties._raw?.[getCSVColumn(resourceKey)]
if (value === 'Available') {
return PALETTE.hasResources // Green
}
}
return PALETTE.noResources // Black
}
/**
* Check if feature has ANY resource (for hasResources).
*/
export function hasAnyResource(properties) {
for (const resourceKey of RESOURCE_PRIORITY) {
const value = properties[resourceKey] || properties._raw?.[getCSVColumn(resourceKey)]
if (value === 'Available') {
return true
}
}
return false
}
/**
* Get the highest priority resource type for a feature.
* Returns the resource key that determines the pin color.
*/
export function getResourceType(properties) {
for (const resourceKey of RESOURCE_PRIORITY) {
const value = properties[resourceKey] || properties._raw?.[getCSVColumn(resourceKey)]
if (value === 'Available') {
return resourceKey
}
}
return 'noResources'
}
/**
* Build Mapbox color expression for gospel resources.
* DEFAULT: Binary coloring - Green if has ANY resource, Black if none.
*/
export function applyColor() {
return [
'case',
// If ANY resource is Available → Green (hasResources)
['any',
['==', ['get', 'bible'], 'Available'],
['==', ['get', 'jesusFilm'], 'Available'],
['==', ['get', 'radio'], 'Available'],
['==', ['get', 'gospel'], 'Available'],
['==', ['get', 'audio'], 'Available'],
['==', ['get', 'stories'], 'Available']
],
PALETTE.hasResources, // Green
// Default: No resources → Black
PALETTE.noResources // Black
]
}
export const buildColorExpression = applyColor
export default {
name: 'Gospel Resources',
propertyKey: PROPERTY_KEY,
palette: PALETTE,
colors: PALETTE,
names: NAMES,
priority: RESOURCE_PRIORITY,
getColor,
applyColor,
buildColorExpression,
hasAnyResource,
getResourceType,
getCSVColumn
}