You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
6.3 KiB
141 lines
6.3 KiB
<script lang="ts">
|
|
import CodeBlock from '../../_components/CodeBlock.svelte';
|
|
import ModuleHeader from '../../_components/ModuleHeader.svelte';
|
|
import PageNav from '../../_components/PageNav.svelte';
|
|
|
|
const quickStart = `import { createActiveApp } from '$active-app';
|
|
import { defineActiveDom, defineActiveFormat } from '$active-app/services';
|
|
import { createActivePrefsDomProjection } from '$prefs';
|
|
|
|
const App = createActiveApp({
|
|
prefs: {
|
|
capabilities,
|
|
environment,
|
|
intent: {
|
|
language: 'es',
|
|
locale: 'es-ES',
|
|
motion: 'system',
|
|
timezone: 'Europe/Madrid'
|
|
}
|
|
},
|
|
services: {
|
|
dom: defineActiveDom(),
|
|
format: defineActiveFormat({})
|
|
}
|
|
});
|
|
|
|
const prefsProjection = createActivePrefsDomProjection({
|
|
prefs: App.prefs,
|
|
dom: App.dom
|
|
});
|
|
|
|
App.prefs.motion.set('reduce');
|
|
const locale = App.prefs.locale.get();`;
|
|
|
|
const sources = `import { readActivePrefsSlot } from '$prefs';
|
|
|
|
const localeSlot = readActivePrefsSlot(App.prefs, 'locale');
|
|
const directionSlot = readActivePrefsSlot(App.prefs, 'direction');
|
|
|
|
const locale = localeSlot?.get();
|
|
const stop = directionSlot?.onChange((direction) => {
|
|
console.log(direction);
|
|
});`;
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<title>Prefs ($prefs) - Active</title>
|
|
</svelte:head>
|
|
|
|
<article class="article">
|
|
<ModuleHeader
|
|
section="Preferences & Environment"
|
|
title="Prefs"
|
|
alias="$prefs"
|
|
summary="Core preference engine for user intent, environment defaults, effective values and bridges consumed by format, langs and DOM projectors."
|
|
factories={['createEnginePrefs', 'createActivePrefs', 'createPrefsStorageBridge']}
|
|
dependsOn={['$storage bridge (optional)']}
|
|
layer="Core (App.prefs) / EnginePrefs / ActivePrefs"
|
|
/>
|
|
|
|
<h2>Overview</h2>
|
|
<p>
|
|
Prefs is part of the <code>$active-app</code> core. Every App has <code>App.prefs</code>,
|
|
even when the application does not declare any services. The engine separates what the user
|
|
wants from what the environment provides: it receives intent, capabilities and environment;
|
|
then resolves an effective preference snapshot for locale, language, timezone, motion,
|
|
sound, haptic, direction, currency and unit system.
|
|
</p>
|
|
<p>
|
|
Format, Langs, DOM projections and feature modules should read from Prefs through source
|
|
helpers instead of each module inventing its own settings model. Storage persistence is
|
|
handled through the storage bridge, not by presentation services.
|
|
</p>
|
|
|
|
<h2>Quick start</h2>
|
|
<CodeBlock code={quickStart} lang="ts" title="App core prefs" />
|
|
|
|
<h2>Source helpers</h2>
|
|
<p>
|
|
The source helpers expose narrow contracts so other modules can subscribe to only the
|
|
preference they need.
|
|
</p>
|
|
<CodeBlock code={sources} lang="ts" title="Bridge into other modules" />
|
|
|
|
<table>
|
|
<thead>
|
|
<tr><th>Slot</th><th>Feeds</th><th>Purpose</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td><code>readActivePrefsSlot(prefs, 'locale')</code></td><td>Format</td><td>Regional BCP 47 locale for numbers, dates and currency.</td></tr>
|
|
<tr><td><code>readActivePrefsSlot(prefs, 'language')</code></td><td>Langs</td><td>Translation language.</td></tr>
|
|
<tr><td><code>readActivePrefsSlot(prefs, 'direction')</code></td><td>DOM projection</td><td>LTR/RTL document direction.</td></tr>
|
|
<tr><td><code>readActivePrefsSlot(prefs, 'motion')</code></td><td>DOM projection / events</td><td>Motion preference for perception and animation behavior.</td></tr>
|
|
<tr><td><code>readActivePrefsSlot(prefs, 'sound')</code></td><td>DOM projection / events</td><td>Sound preference for perceptive feedback.</td></tr>
|
|
<tr><td><code>readActivePrefsSlot(prefs, 'haptic')</code></td><td>DOM projection / events</td><td>Haptic preference for perceptive feedback.</td></tr>
|
|
<tr><td><code>readActivePrefsSlot(prefs, 'timezone')</code></td><td>Format</td><td>Timezone for date/time display.</td></tr>
|
|
<tr><td><code>readActivePrefsSlot(prefs, 'currency')</code></td><td>Format</td><td>Currency preference.</td></tr>
|
|
<tr><td><code>readActivePrefsSlot(prefs, 'unitSystem')</code></td><td>Format</td><td>Metric/imperial domain defaults.</td></tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<h2>Runtime API</h2>
|
|
<table>
|
|
<thead>
|
|
<tr><th>Member</th><th>Purpose</th><th>Notes</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td><code>state.snapshot</code></td><td>Full preference snapshot.</td><td>Reactive in ActivePrefs.</td></tr>
|
|
<tr><td><code>state.effective</code></td><td>Resolved values.</td><td>Combines intent, environment and capabilities.</td></tr>
|
|
<tr><td><code>setIntent(key, value)</code></td><td>Apply one user preference intent.</td><td>Use for UI settings controls.</td></tr>
|
|
<tr><td><code>clearIntent(key)</code></td><td>Return one preference to environment/defaults.</td><td>Useful for "system" mode.</td></tr>
|
|
<tr><td><code>resetIntent(next?)</code></td><td>Replace the whole intent map.</td><td>Use for hydration or full reset.</td></tr>
|
|
<tr><td><code>refreshEnvironment(next)</code></td><td>Update detected environment.</td><td>Browser/server adapters call this.</td></tr>
|
|
<tr><td><code>setCapabilities(capabilities)</code></td><td>Constrain valid values.</td><td>Prevents unsupported modes.</td></tr>
|
|
<tr><td><code>pending / lastError</code></td><td>Async bridge placeholders.</td><td>Reserved for storage bridge and future async adapters.</td></tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<h2>Adapters</h2>
|
|
<ul>
|
|
<li><code>detectBrowserEnvironment()</code> reads browser locale, timezone, color scheme and motion hints.</li>
|
|
<li><code>watchBrowserEnvironment()</code> keeps environment in sync when browser settings change.</li>
|
|
<li><code>detectServerEnvironment()</code> derives initial values from request headers.</li>
|
|
<li><code>createPrefsStorageBridge()</code> persists intent through the storage module.</li>
|
|
</ul>
|
|
|
|
<h2>Testing</h2>
|
|
<table>
|
|
<thead>
|
|
<tr><th>Target</th><th>Purpose</th><th>Notes</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td><code>src/arts/prefs/test/engine-prefs.test.ts</code></td><td>Resolution engine.</td><td>Intent, environment, capabilities and reset behavior.</td></tr>
|
|
<tr><td><code>src/arts/prefs/test/dom-projection.test.ts</code></td><td>DOM projection.</td><td>Direction, motion, sound and haptic attrs.</td></tr>
|
|
<tr><td><code>src/arts/prefs/test/storage-bridge.test.ts</code></td><td>Persistence bridge.</td><td>Storage integration without UI coupling.</td></tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<PageNav />
|
|
</article>
|