Add a reviewed `theme` plugin kind (interfaceVersion 1, export `theme`, switch
"list"). A module returns data only: a displayName and a flat map of colour
custom properties for light, dim and dark. checkTheme validates names and
#rrggbb colours strictly and checks each text/background pair for contrast; a
bad module is refused and logged, never served.
The ten shipped palettes become the first ten modules under
packages/plugins/theme/<name>/. Modules are found by directory scan
(loader.discoverModules, loader.loadInstalled), not by a list in the Console.
loadModule and createLoader are unchanged.
The organization file takes `appearance: { theme, mode }`, validated in
packages/business/src/appearance.mjs; a missing appearance is valid.
GET /api/themes (themes-http.mjs) serves the installed, valid themes.
Browser: the Settings picker lists /api/themes. Precedence is a per-organization
browser override, then the organization's saved theme, then the built-in default
(Harbor, dark). Clearing the override restores the organization's choice. An
uninstalled or invalid saved theme renders the default with a visible warning
and keeps the saved value. A legacy global browser preference is not copied to
every organization. The organization is named in text, so colour is never the
only cue. A plain load writes no appearance record. The default look is
unchanged: computed styles match the base commit element for element.
12 lines
396 B
JSON
12 lines
396 B
JSON
{
|
|
"name": "@mosaic/plugins",
|
|
"version": "0.1.0",
|
|
"private": true,
|
|
"description": "Plug-in kind registry and in-repo module loader (PRD 1.2 row 131).",
|
|
"license": "UNLICENSED",
|
|
"type": "module",
|
|
"engines": { "node": ">=24" },
|
|
"exports": { "./kinds": "./src/kinds.mjs", "./loader": "./src/loader.mjs", "./theme": "./src/theme.mjs" },
|
|
"scripts": { "test": "node --test tests/" }
|
|
}
|