Align Active docs with prefs projection

active-uix
dev 5 months ago
parent 26b9b83eb5
commit 501f55b0cc

@ -10,7 +10,8 @@ Fecha de corte: 2026-05-13. Rama: `active-uix`.
- El servicio runtime de traducciones se llama `langs`. No confundir:
- `prefs.language` alimenta `langs`.
- `prefs.locale` alimenta `format`.
- `prefs.direction` proyecta `html[dir]` via `uix.dom`.
- `prefs.direction`, `prefs.motion`, `prefs.sound` y `prefs.haptic` se
proyectan mediante `createActivePrefsDomProjection(...)`.
- `events` es el nombre publico del motor perceptivo en `ActiveUix`; `semantic` queda solo como payload de `morfo.events[].semantic`.
- `ActiveEidos` queda aplanado: no existe engine visual separado ni directorio `engine` bajo Eidos.
- Los helpers de configuracion/render/persistencia de Eidos viven en `src/uix/eidos/lib`.
@ -62,8 +63,9 @@ a su `portalTo`. No usar nombres como `somaPortalTo` en `ActiveUix`.
5. `attachActiveUix(app)` no crea sustitutos si faltan servicios requeridos.
6. `SoundChannel` ya no registra listeners globales en el constructor; prima
el contexto en `prepare()` solo cuando una senal sonora entra en el gesto.
7. `ActiveUix` proyecta `prefs.theme` como `data-mode`; `ActiveEidos`
proyecta el theme id real como `data-theme`.
7. `createActivePrefsDomProjection(...)` proyecta `dir`, `data-motion`,
`data-sound` y `data-haptic`; `ActiveEidos` proyecta `data-theme`,
`data-mode` y `data-density`.
8. `SomaRuntime`, `registerMorfo` y `applyMapOverrides` tienen optimizaciones
basicas de churn/copia aplicadas.
@ -79,8 +81,9 @@ a su `portalTo`. No usar nombres como `somaPortalTo` en `ActiveUix`.
3. Morfo translations: mantener `translations` en el morfo, `commonRef` para
textos compartidos y `langs.ts` solo como constantes imperativas legacy.
4. Frontend/ActiveApp: cerrado para esta fase. `frontend` es servicio legacy
opt-in; no pertenece al core de `ActiveApp` ni a UIX. `ActiveUix` proyecta
preferencias UIX con `uix.dom`.
opt-in; no pertenece al core de `ActiveApp` ni a UIX. Las preferencias
transversales se proyectan desde `arts/prefs`; las visuales pertenecen a
`ActiveEidos`.
5. ActiveApp docs: actualizado que `langs`, `dom`, `format`, `events` y
`frontend` son servicios opt-in, y que `frontend` no debe usarse para
codigo UIX nuevo.
@ -95,7 +98,7 @@ a su `portalTo`. No usar nombres como `somaPortalTo` en `ActiveUix`.
2. Mantener `EidosConfig` como authoring object persistible y CSS-only como
modo valido mediante `themeSource: 'css'`.
3. Density queda como primitive bridge: `scale`, `spaceScale`, `controlScale`
y `contentScale` para `compact`, `comfortable`, `spacious`; `ActiveUix`
y `contentScale` para `compact`, `comfortable`, `spacious`; `ActiveEidos`
proyecta `data-density` y Eidos publica aliases activos como
`--density-space-scale`.
4. Pendiente: introducir un artefacto CSS generado en build desde

@ -6,24 +6,30 @@
const composition = `import { createActiveApp } from '$active-app';
import {
defineActiveLangs,
defineActiveFrontend,
defineActiveDom,
defineActiveFormat
} from '$active-app/services';
import { createActivePrefsDomProjection } from '$prefs';
const App = createActiveApp({
logger: { level: LogLevel.INFO, transports: [consoleTransport()] },
prefs: {
capabilities,
environment,
intent: { language: 'es', locale: 'es-MX', theme: 'system' }
intent: { language: 'es', locale: 'es-MX' }
},
services: {
dom: defineActiveDom(),
langs: defineActiveLangs({ schema, defaultLocale: 'es', fallbackChain: ['en'] }),
frontend: defineActiveFrontend({}),
format: defineActiveFormat({})
}
});
const prefsProjection = createActivePrefsDomProjection({
prefs: App.prefs,
dom: App.dom
});
App.langs.t('common.ok');
App.format.currency.format(99.5);
App.prefs.locale.set('es-MX');
@ -155,10 +161,10 @@ App.bus.publish('app.ready', {});`;
title: 'UI Layer',
items: [
{
title: 'Frontend',
title: 'Frontend (legacy)',
alias: '$frontend',
href: '/active/docs/fend',
description: 'Frontend preferences: theme, mode, dir, density.',
description: 'Legacy presentation shell; new UIX apps use prefs projection and Eidos.',
factories: ['createActiveFrontend']
},
{
@ -241,7 +247,7 @@ App.bus.publish('app.ready', {});`;
<p class="lead">
A composable set of <strong>runtime artifacts</strong> — core App infrastructure,
i18n, preferences, logger, sessions, auth, permissions, cache, storage, HTTP, timers,
formatting, orchestration, realtime connections and a reactive frontend layer.
formatting, orchestration, realtime connections and DOM-aware preference projection.
</p>
<div class="cta">
<a class="btn primary" href="/active/get-started/installation">

@ -2997,8 +2997,7 @@ App.prefs.locale.set('es-AR');
App.langs.t('common.ok');
App.format.currency.getCurrency(); // ARS
App.format.dates.getDateOrder();
App.frontend.getDir();`
App.format.dates.getDateOrder();`
}
},
{
@ -3070,17 +3069,17 @@ Format.currency.getCurrency(); // USD, explicit user choice`
title: 'Frontend',
alias: '$frontend',
summary:
'Application-level frontend preferences: dir, theme, mode, density, reduced motion and reduced sound, applied through adom.',
'Legacy application-level presentation shell. New UIX code uses prefs DOM projection plus Eidos.',
factories: ['createActiveFrontend'],
dependsOn: ['$adom', '$locale'],
layer: 'ActiveFrontend',
overview: [
'Frontend is not a component system. It owns global presentation preferences and writes stable attributes to the configured DOM target.',
'dir, mode and reducedMotion can be auto. theme, density and reducedSound are explicit preferences. The same auto/manual dynamic used by Format applies here.',
'When built through App, Frontend consumes core App.prefs plus optional App.dom and App.langs services. Prefs drives mode, density, motion and direction; Lang remains a fallback locale source only when the preference snapshot has no effective locale.'
'Frontend is not a component system. It is a legacy presentation shell kept for older consumers.',
'New UIX code should project cross-modal prefs with createActivePrefsDomProjection() and let ActiveEidos own theme, mode and density.',
'When built through App, Frontend may still consume explicitly declared legacy prefs slots plus optional App.dom.'
],
dynamics: [
'Frontend reads locale and environment preferences, resolves auto-capable values, and writes the result to DOM attributes through Dom.apply(). Components then style against those attributes instead of each component recalculating theme, direction or density.',
'Legacy Frontend reads locale and environment preferences, resolves auto-capable values, and writes the result to DOM attributes through Dom.apply().',
'The auto/manual dynamic matches Format. While dir/mode/reducedMotion are auto, locale or media-query changes can update them. Once the user sets a value explicitly, later auto sources stop overriding it until clearX() is called.',
'Persistence is not owned by Frontend. User intent belongs to prefs, and persistence is handled by the prefs storage bridge or application code.'
],
@ -3098,7 +3097,7 @@ Format.currency.getCurrency(); // USD, explicit user choice`
{
name: 'using Frontend as a component library',
purpose: 'It only owns global presentation state.',
notes: 'Use UI components separately; use $frontend for app-level preferences.'
notes: 'Use UIX components separately; use $frontend only for legacy app-level presentation state.'
},
{
name: 'persisting every preference blindly',
@ -3108,7 +3107,7 @@ Format.currency.getCurrency(); // USD, explicit user choice`
],
quickStart: {
title: 'Direction and theme',
code: `const Frontend = App.frontend;
code: `const Frontend = App.frontend; // legacy service
App.prefs.language.set('ar');
Frontend.getDir(); // rtl while dir is auto
@ -3129,7 +3128,7 @@ Frontend.getDir(); // rtl`
{
name: 'App.frontend',
purpose: 'Schema-declared frontend service.',
notes: 'Wired to core App.prefs and optional App.dom/App.langs services when they exist.'
notes: 'Legacy opt-in service; not part of the new UIX boot path.'
}
],
api: artifactApis.fend,
@ -3137,7 +3136,7 @@ Frontend.getDir(); // rtl`
{
title: 'Creation and app wiring',
body: [
'Frontend should normally be declared as an App service. The factory reads Dom from the service schema and Prefs from the core (always present).',
'Frontend is legacy opt-in. New UIX code should prefer createActivePrefsDomProjection() and ActiveEidos.',
'Create ActiveFrontend directly only for tests or embedded widgets that intentionally own their own DOM target.'
],
code: {
@ -3168,8 +3167,8 @@ App.frontend.getDir(); // rtl while dir remains auto`
dir="rtl"
data-theme="base"
data-mode="light"
data-reduced-motion="false"
data-reduced-sound="false"
data-motion="allow"
data-sound="allow"
data-density="normal"
></html>`
}
@ -3189,7 +3188,7 @@ App.frontend.getDir(); // rtl while dir remains auto`
},
services: {
storage: defineActiveStorage({ adapter: localAdapter, namespace: 'app' }),
frontend: defineActiveFrontend({ theme: 'base' })
frontend: defineActiveFrontend({ theme: 'base' }) // legacy opt-in
}
});`
}
@ -3204,7 +3203,7 @@ App.frontend.getDir(); // rtl while dir remains auto`
{
name: 'src/arts/active-app/test/prefs-consumer-wiring.test.ts',
purpose: 'Prefs bridge.',
notes: 'Core Prefs drives Frontend mode, density, motion and direction when the Frontend service is declared.'
notes: 'Covers legacy Frontend prefs wiring when the Frontend service is declared.'
},
{
name: '/test/fend',
@ -3224,14 +3223,14 @@ App.frontend.getDir(); // rtl while dir remains auto`
dependsOn: ['$libs/dom', '$reactive'],
layer: 'ActiveDom',
overview: [
'Dom is the runtime DOM layer. It keeps browser-specific behavior out of formatting, frontend preferences and feature modules.',
'Dom is the runtime DOM layer. It keeps browser-specific behavior out of formatting, preference projection and feature modules.',
'It can resolve responsive values, track viewport, apply attributes declaratively and coordinate scroll lock. In SSR, browser tracking is inert.',
'Frontend uses Dom.apply() to update application-level attrs, so theme/dir changes are centralized.'
'Prefs projection and ActiveEidos use Dom.apply() to update application-level attrs.'
],
dynamics: [
'In the browser, ActiveDom installs viewport/media listeners and updates a reactive viewport snapshot. During SSR those listeners are inert so imports stay safe.',
'Responsive values are resolved from the current breakpoint. Consumers can pass a scalar or a breakpoint map and receive the best value for the active viewport.',
'DOM writes are centralized through apply(). Frontend uses this to update html/body attributes, while feature modules can use the same writer for controlled attribute/class/style updates.'
'DOM writes are centralized through apply(). Prefs projection, Eidos and feature modules use the same writer for controlled attribute/class/style updates.'
],
commonMistakes: [
{
@ -3250,9 +3249,9 @@ App.frontend.getDir(); // rtl while dir remains auto`
notes: 'Resolve responsive maps through Dom.resolve().'
},
{
name: 'manual attrs fighting Frontend',
purpose: 'Theme/dir/mode can be overwritten by the next preference update.',
notes: 'Let Frontend write app-level attrs through Dom.'
name: 'manual attrs fighting managed projection',
purpose: 'dir, mode or theme attrs can be overwritten by the owning projection.',
notes: 'Use createActivePrefsDomProjection(), ActiveEidos or Dom.apply() from the owning layer.'
}
],
quickStart: {
@ -3264,8 +3263,7 @@ const size = Dom.resolve({ base: 'compact', md: 'comfortable' });
Dom.apply({
target: document.documentElement,
attrs: {
dir: App.frontend.getDir(),
'data-theme': App.frontend.getTheme()
'data-app-ready': true
}
});`
},
@ -3278,7 +3276,7 @@ Dom.apply({
{
name: 'App.dom',
purpose: 'Schema-declared DOM service.',
notes: 'Shared by Frontend and consumers when declared.'
notes: 'Shared by prefs projection, Eidos and consumers when declared.'
}
],
api: artifactApis.adom,
@ -3320,7 +3318,7 @@ const layout = Dom.resolve({ base: 'stack', md: 'split' });`
{
name: 'apply()',
purpose: 'Apply attrs/styles/classes declaratively.',
notes: 'Used by Frontend.'
notes: 'Used by prefs projection, Eidos and controlled feature modules.'
},
{
name: 'scroll lock',
@ -3344,8 +3342,8 @@ const layout = Dom.resolve({ base: 'stack', md: 'split' });`
},
{
name: 'src/arts/frontend/test',
purpose: 'Frontend integration.',
notes: 'Frontend applies attrs through Dom.'
purpose: 'Legacy Frontend integration.',
notes: 'Legacy Frontend applies attrs through Dom.'
},
{
name: '/test/adom',

@ -9,12 +9,13 @@
import {
defineActiveLangs,
defineActiveFormat,
defineActiveFrontend,
defineActiveDom,
defineActiveCache,
defineActiveSession,
defineActivePerm,
defineActiveConnections
} from '$active-app/services';
import { createActivePrefsDomProjection } from '$prefs';
import { applyStandardOrca } from '$active-app/presets';
import { LogLevel, consoleTransport } from '$logger';
@ -23,9 +24,9 @@ export const App = createActiveApp({
orca: { maxDepth: 24 },
prefs: { capabilities, environment, intent },
services: {
dom: defineActiveDom(),
langs: defineActiveLangs({ schema, defaultLocale: 'es', fallbackChain: ['en'] }),
format: defineActiveFormat(),
frontend: defineActiveFrontend({ theme: 'base' }),
cache: defineActiveCache(),
session: defineActiveSession({ schemas, storage, onRefresh, onRevoke }),
perm: defineActivePerm({ endpoint: '/api/perm' }),
@ -33,19 +34,23 @@ export const App = createActiveApp({
}
});
export const prefsProjection = createActivePrefsDomProjection({
prefs: App.prefs,
dom: App.dom
});
applyStandardOrca(App);`;
const access = `App.logger.info('checkout.paid', { orderId });
App.prefs.locale.set('es-MX');
App.langs.t('common.ok');
App.format.currency.format(99.5);
App.frontend.setMode('dark');
App.cache.clear();`;
const factories = `import {
defineActiveLangs,
defineActiveFormat,
defineActiveFrontend,
defineActiveDom,
defineActiveStorage,
defineEngineHttp,
defineEngineSium,
@ -61,9 +66,9 @@ const App = createActiveApp({
services: {
storage: defineActiveStorage(),
http: defineEngineHttp({ baseUrl: '/api' }),
dom: defineActiveDom(),
langs: defineActiveLangs({ schema }),
format: defineActiveFormat(),
frontend: defineActiveFrontend(),
sium: defineEngineSium({}),
cache: defineActiveCache(),
session: defineActiveSession({ schemas, storage, onRefresh, onRevoke }),
@ -98,7 +103,7 @@ onDestroy(() => App.dispose());`;
},
{
name: 'Bypassing prefs for user intent',
why: 'Lang, Format and Frontend can disagree about language, locale, theme or direction.',
why: 'Lang, Format and DOM projection can disagree about language, locale or direction.',
fix: 'Use App.prefs.<dim>.set(value) (e.g. App.prefs.locale.set("es-ES")); downstream services follow the effective snapshot.'
},
{
@ -230,7 +235,7 @@ onDestroy(() => App.dispose());`;
<tbody>
<tr><td><code>lang</code></td><td><code>defineActiveLangs()</code></td><td>Consumes <code>logger</code> and <code>prefs</code> from the core; follows <code>App.prefs.language.get()</code>.</td></tr>
<tr><td><code>format</code></td><td><code>defineActiveFormat()</code></td><td>Consumes <code>timers</code> and <code>prefs</code> from the core; resolves locale from explicit source or prefs.</td></tr>
<tr><td><code>frontend</code></td><td><code>defineActiveFrontend()</code></td><td>Consumes <code>prefs</code> from the core and optionally <code>dom</code>; prefs drives mode, density, motion and direction.</td></tr>
<tr><td><code>frontend</code></td><td><code>defineActiveFrontend()</code></td><td>Legacy opt-in presentation shell. New UIX code uses prefs projection plus Eidos.</td></tr>
<tr><td><code>dom</code></td><td><code>defineActiveDom()</code></td><td>DOM integration, isolated as a service.</td></tr>
<tr><td><code>storage</code></td><td><code>defineActiveStorage()</code></td><td>Storage runtime, typically used by session and prefs persistence bridges.</td></tr>
<tr><td><code>http</code></td><td><code>defineEngineHttp()</code></td><td>Pure HTTP engine adapted into the schema.</td></tr>
@ -248,9 +253,8 @@ onDestroy(() => App.dispose());`;
<code>App.prefs</code> is always present and is the core source for user intent.
<code>lang</code> follows <code>App.prefs.language.get()</code>,
<code>format</code> follows <code>App.prefs.locale.get()</code>, and
<code>frontend</code> follows theme, density, motion and direction. Direct service
overrides still work where the service exposes them, but the next Prefs update becomes
authoritative again.
shared prefs such as direction, motion, sound and haptic can be projected explicitly
through <code>createActivePrefsDomProjection()</code>.
</p>
<h2>Bus and Orca</h2>

@ -4,7 +4,7 @@
import PageNav from '../../_components/PageNav.svelte';
const quickStart = `import { createActiveApp } from '$active-app';
import { defineActiveDom, defineActiveFrontend, defineActiveFormat } from '$active-app/services';
import { defineActiveDom, defineActiveFormat } from '$active-app/services';
import { createActivePrefsDomProjection } from '$prefs';
const App = createActiveApp({
@ -20,7 +20,6 @@ const App = createActiveApp({
},
services: {
dom: defineActiveDom(),
frontend: defineActiveFrontend({}),
format: defineActiveFormat({})
}
});
@ -33,13 +32,15 @@ const prefsProjection = createActivePrefsDomProjection({
App.prefs.motion.set('reduce');
const locale = App.prefs.locale.get();`;
const sources = `import {
prefsLocaleSource,
prefsDirectionSource
} from '$prefs';
const sources = `import { readActivePrefsSlot } from '$prefs';
const localeSource = prefsLocaleSource(App.prefs);
const directionSource = prefsDirectionSource(App.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>
@ -51,7 +52,7 @@ const directionSource = prefsDirectionSource(App.prefs);`;
section="Preferences & Environment"
title="Prefs"
alias="$prefs"
summary="Core preference engine for user intent, environment defaults, effective values and bridges consumed by frontend, format and lang."
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"
@ -66,9 +67,9 @@ const directionSource = prefsDirectionSource(App.prefs);`;
sound, haptic, direction, currency and unit system.
</p>
<p>
Frontend, Format and Lang 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 frontend.
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>
@ -83,17 +84,18 @@ const directionSource = prefsDirectionSource(App.prefs);`;
<table>
<thead>
<tr><th>Helper</th><th>Feeds</th><th>Purpose</th></tr>
<tr><th>Slot</th><th>Feeds</th><th>Purpose</th></tr>
</thead>
<tbody>
<tr><td><code>prefsLocaleSource()</code></td><td>Format</td><td>Regional BCP 47 locale for numbers, dates and currency.</td></tr>
<tr><td><code>prefsLanguageSource()</code></td><td>Lang / Frontend</td><td>Translation language and writing-system direction source.</td></tr>
<tr><td><code>prefsDirectionSource()</code></td><td>Frontend / Dom</td><td>LTR/RTL direction.</td></tr>
<tr><td><code>prefsThemeSource()</code></td><td>Frontend</td><td>Theme intent/effective value.</td></tr>
<tr><td><code>prefsDensitySource()</code></td><td>Frontend / UI</td><td>Density preference.</td></tr>
<tr><td><code>prefsTimezoneSource()</code></td><td>Format</td><td>Timezone for date/time display.</td></tr>
<tr><td><code>prefsCurrencySource()</code></td><td>Format</td><td>Currency preference.</td></tr>
<tr><td><code>prefsUnitSystemSource()</code></td><td>Format</td><td>Metric/imperial domain defaults.</td></tr>
<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>

@ -25,12 +25,13 @@
import {
defineActiveLangs,
defineActiveFormat,
defineActiveFrontend,
defineActiveDom,
defineActiveStorage,
defineEngineHttp,
defineActiveSession,
defineActiveCache
} from '$active-app/services';
import { createActivePrefsDomProjection } from '$prefs';
import { applyStandardOrca } from '$active-app/presets';
import { LogLevel, consoleTransport } from '$logger';
@ -43,9 +44,9 @@ export const App = createActiveApp({
intent: { language: 'es', locale: 'es-ES' }
},
services: {
dom: defineActiveDom(),
langs: defineActiveLangs({ schema, defaultLocale: 'es', fallbackChain: ['en'] }),
format: defineActiveFormat(),
frontend: defineActiveFrontend(),
storage: defineActiveStorage(),
http: defineEngineHttp({ baseUrl: '/api' }),
session: defineActiveSession({ schemas, storage, onRefresh, onRevoke }),
@ -53,6 +54,11 @@ export const App = createActiveApp({
}
});
export const prefsProjection = createActivePrefsDomProjection({
prefs: App.prefs,
dom: App.dom
});
applyStandardOrca(App);`;
const orcaExample = `import {

@ -16,12 +16,12 @@ const appFlow = `const App = createActiveApp({
prefs: {
capabilities,
environment,
intent: { language: 'es', locale: 'es-ES', theme: 'system' }
intent: { language: 'es', locale: 'es-ES' }
},
services: {
dom: defineActiveDom(),
langs: defineActiveLangs({ schema, defaultLocale: 'es', fallbackChain: ['en'] }),
storage: defineActiveStorage({ adapter: localAdapter, namespace: 'app' }),
frontend: defineActiveFrontend({ theme: 'base' }),
http: defineEngineHttp({ baseUrl: '/api' }),
cache: defineActiveCache({ defaultPolicy: 'interactive' }),
sium: defineEngineSium({}),
@ -32,6 +32,11 @@ const appFlow = `const App = createActiveApp({
}
});
const prefsProjection = createActivePrefsDomProjection({
prefs: App.prefs,
dom: App.dom
});
applyStandardOrca(App); // wires cache, perm and connections reactions through App.orca`;
const serverFlow = `const Auth = createEngineAuth({
@ -77,8 +82,8 @@ App.prefs.locale.set('ar-EG')
-> prefs resolves effective language and regional locale
-> App.langs follows App.prefs.language.get()
-> App.format follows App.prefs.locale.get()
-> App.frontend follows App.prefs language, theme, density, motion and direction
-> Dom writes dir="rtl" to the configured target when frontend direction changes`;
-> prefs projection writes dir="rtl" and cross-modal attrs through App.dom
-> ActiveEidos owns data-theme, data-mode and data-density when UIX is mounted`;
</script>
<svelte:head>
@ -165,9 +170,9 @@ App.prefs.locale.set('ar-EG')
<tr><td>Composition</td><td><code>$active-app</code></td><td>Single client root, fixed Logger/Bus/Timers/Orca/Prefs core, typed service schema and disposal order.</td></tr>
<tr><td>Identity</td><td><code>$auth</code>, <code>$session</code>, <code>$perm</code></td><td>Prove identity, keep session continuity, decide access.</td></tr>
<tr><td>Data</td><td><code>$http</code>, <code>$cache</code>, <code>$storage</code></td><td>Remote calls, coherent cached data, safe local persistence.</td></tr>
<tr><td>Preferences</td><td><code>$prefs</code></td><td>User intent, environment defaults and effective locale/theme/density/timezone values.</td></tr>
<tr><td>Preferences</td><td><code>$prefs</code></td><td>User intent, environment defaults and effective locale/timezone/perception values.</td></tr>
<tr><td>I18n and formats</td><td><code>$langs</code>, <code>$format</code></td><td>Text translation plus preference-driven numbers, currency, units and dates.</td></tr>
<tr><td>Frontend runtime</td><td><code>$frontend</code>, <code>$adom</code></td><td>Effective visual state, direction, theme, DOM writes and responsive helpers.</td></tr>
<tr><td>DOM and UI runtime</td><td><code>$adom</code>, <code>$prefs</code>, <code>$uix/eidos</code></td><td>DOM writes, global preference attrs and visual theme/mode/density.</td></tr>
<tr><td>Validation</td><td><code>$sium</code></td><td>Page-scoped schemas, issues, metadata and translated validation messages.</td></tr>
<tr><td>Infrastructure</td><td><code>$bus</code>, <code>$logger</code>, <code>$timer</code>, <code>$orca</code>, <code>$connection</code></td><td>Events, structured logs, deterministic timers, orchestration and realtime connections.</td></tr>
</tbody>
@ -231,7 +236,7 @@ App.prefs.locale.set('ar-EG')
<h2>Locale flow</h2>
<p>
Preferences are the ecosystem-wide source of user intent. Translation language, regional
format locale and frontend direction can be related, but they are not the same value.
format locale and document direction can be related, but they are not the same value.
</p>
<CodeBlock code={localeFlow} lang="text" />

@ -134,7 +134,7 @@ App.logger.info('app.boot', 'Active app ready');`}
</p>
<h2>Realistic setup</h2>
<p>For typed i18n, preferences, formatting, frontend state and storage:</p>
<p>For typed i18n, preferences, formatting, DOM projection and storage:</p>
<CodeBlock
lang="ts"
@ -143,9 +143,10 @@ App.logger.info('app.boot', 'Active app ready');`}
import {
defineActiveLangs,
defineActiveFormat,
defineActiveFrontend,
defineActiveDom,
defineActiveStorage
} from '$active-app/services';
import { createActivePrefsDomProjection } from '$prefs';
import { LogLevel, consoleTransport } from '$logger';
import { localAdapter } from '$storage';
import { schema } from './i18n/schema';
@ -155,14 +156,19 @@ export const App = createActiveApp({
prefs: {
capabilities,
environment,
intent: { language: 'es', locale: 'es-ES', theme: 'system' }
intent: { language: 'es', locale: 'es-ES' }
},
services: {
dom: defineActiveDom(),
langs: defineActiveLangs({ schema, defaultLocale: 'es', fallbackChain: ['en'] }),
format: defineActiveFormat(),
frontend: defineActiveFrontend({ theme: 'base' }),
storage: defineActiveStorage({ adapter: localAdapter })
}
});
export const prefsProjection = createActivePrefsDomProjection({
prefs: App.prefs,
dom: App.dom
});`}
/>

@ -20,7 +20,7 @@ createActiveApp({ prefs: { capabilities }, services: { /* ... */ } });
defineActiveLangs({ schema });
defineActiveFormat({});
defineActiveFrontend({});
defineActiveDom({});
defineActiveStorage({});
defineEngineHttp({});
defineActiveCache({});

Loading…
Cancel
Save

Powered by TurnKey Linux.