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.
svelte-kit-vice/web/routes/temas/grafito/+layout@.svelte

213 lines
5.8 KiB

<script lang="ts">
/**
* Shell del tema Grafito.
*
* Arranca su propio `ActiveUix` + `Soma` + `ActiveEidos` (igual que la
* docs-site de UIX) pero con el patch de tema `untitled-ui`. Es la
* raíz de composición de esta ruta: posee modo (claro/oscuro) y
* densidad, que se inyectan a Eidos como fuentes visuales.
*
* `+layout@.svelte` resetea la herencia al layout raíz (passthrough),
* así esta ruta no hereda el chrome de `/uix`.
*/
import { onDestroy } from 'svelte'
import type { Density } from '$libs/density'
import type { ThemeEffective } from '$libs/theme'
import { createActiveUix, setActiveUix } from '$active-uix'
import { Soma } from '$soma/core/soma.svelte'
import { siumLangs } from '$sium/langs/langs'
import { secsLangs } from '$libs/secs'
import { ActiveEidos, SCALING_KEYS, type ScalingKey } from '$uix/eidos'
import {
accordionSema,
checkboxSema,
contextMenuSema,
dialogSema,
dropdownMenuSema,
menubarSema,
popoverSema,
radioGroupSema,
selectSema,
sliderSema,
switchSema,
tabsSema,
toggleSema,
toggleGroupSema,
toolbarSema,
tooltipSema
} from '$uix/sema/components'
import { grafitoConfig } from '../_lib/grafito'
import '@/uix/eidos/index.css'
import './theme.css'
import './grafito.css'
let { children } = $props()
// ── Runtime ───────────────────────────────────────────────────────
// `events` enciende la capa semántica (sema): sonido + haptic + las
// reacciones visuales `data-event-*`. Los packs afinan la cascada por
// componente. Cablearlo además resuelve la hidratación de los
// componentes con portal (menubar / dropdown / tooltip / popover /
// dialog), que acceden a `uix.events` al montar.
const uix = createActiveUix({
langs: { schema: { sium: siumLangs, secs: secsLangs }, defaultLocale: 'es' as const },
events: {
sound: true,
haptic: true,
components: [
accordionSema,
checkboxSema,
contextMenuSema,
dialogSema,
dropdownMenuSema,
menubarSema,
popoverSema,
radioGroupSema,
selectSema,
sliderSema,
switchSema,
tabsSema,
toggleSema,
toggleGroupSema,
toolbarSema,
tooltipSema
]
}
})
setActiveUix(uix)
Soma.create()
// ── Modo + densidad (fuentes visuales para Eidos) ─────────────────
let mode = $state<ThemeEffective>('light')
let density = $state<Density>('comfortable')
let scaling = $state<ScalingKey>('100')
const modeListeners = new Set<(v: ThemeEffective) => void>()
const densityListeners = new Set<(v: Density) => void>()
const scalingListeners = new Set<(v: ScalingKey) => void>()
const activeEidos = ActiveEidos.create({
applyDom: true,
config: grafitoConfig,
theme: 'grafito',
modeSource: {
get: () => mode,
onChange(handler) {
modeListeners.add(handler)
return () => modeListeners.delete(handler)
}
},
densitySource: {
get: () => density,
onChange(handler) {
densityListeners.add(handler)
return () => densityListeners.delete(handler)
}
},
scalingSource: {
get: () => scaling,
onChange(handler) {
scalingListeners.add(handler)
return () => scalingListeners.delete(handler)
}
}
})
$effect(() => {
const m = mode
for (const l of modeListeners) l(m)
})
$effect(() => {
const d = density
for (const l of densityListeners) l(d)
})
$effect(() => {
const s = scaling
for (const l of scalingListeners) l(s)
})
const DENSITIES: { id: Density; label: string }[] = [
{ id: 'compact', label: 'Compact' },
{ id: 'comfortable', label: 'Comfortable' },
{ id: 'spacious', label: 'Spacious' }
]
onDestroy(() => {
activeEidos.dispose()
uix.dispose()
})
</script>
<svelte:head>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Roboto+Mono:wght@400;500&display=swap"
/>
</svelte:head>
<div data-temas-shell>
<header data-temas-topbar>
<div data-temas-brand>
<span data-temas-brand-mark>G</span>
<div data-temas-brand-text>
<strong>Grafito</strong>
<small>Tema · activeUIX / Eidos</small>
</div>
</div>
<div data-temas-tools>
<div data-temas-segmented role="group" aria-label="Densidad">
{#each DENSITIES as d}
<button
type="button"
data-active={density === d.id ? 'true' : 'false'}
onclick={() => (density = d.id)}
>
{d.label}
</button>
{/each}
</div>
<div data-temas-segmented role="group" aria-label="Scaling">
{#each SCALING_KEYS as s}
<button
type="button"
data-active={scaling === s ? 'true' : 'false'}
onclick={() => (scaling = s)}
>
{s}%
</button>
{/each}
</div>
<button
type="button"
data-temas-mode-btn
aria-label="Cambiar modo"
aria-pressed={mode === 'dark'}
onclick={() => (mode = mode === 'light' ? 'dark' : 'light')}
>
{#if mode === 'light'}
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
</svg>
<span>Light</span>
{:else}
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="4" />
<path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41" />
</svg>
<span>Dark</span>
{/if}
</button>
</div>
</header>
<main data-temas-canvas>
{@render children?.()}
</main>
</div>

Powered by TurnKey Linux.