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.
49 lines
1.7 KiB
49 lines
1.7 KiB
<script lang="ts">
|
|
/**
|
|
* `<OnionLayer>` — one concentric ring / level. It does NOT paint; it registers
|
|
* an {@link OnionLayerNode} either as the menu's ROOT layer (when composed
|
|
* directly in `<OnionMenu>`) or as an option's CHILDREN (when composed inside an
|
|
* `<OnionOption>` — it reads the option registry). It exposes a layer registry
|
|
* so its `<OnionOption>`s register in order. The root `<OnionMenu>` paints.
|
|
*/
|
|
import { untrack } from 'svelte';
|
|
import {
|
|
OnionLayerNode,
|
|
getOnionOptionRegistry,
|
|
getOnionMenuRegistry,
|
|
setOnionLayerRegistry
|
|
} from './context.svelte';
|
|
import type { OnionLayerProps } from './types';
|
|
|
|
let { textDisposition, color, display, ringWidth, gap, children }: OnionLayerProps = $props();
|
|
|
|
const option = getOnionOptionRegistry();
|
|
const menu = getOnionMenuRegistry();
|
|
const node = new OnionLayerNode();
|
|
|
|
$effect(() => void (node.textDisposition = textDisposition));
|
|
$effect(() => void (node.color = color));
|
|
$effect(() => void (node.display = display));
|
|
$effect(() => void (node.ringWidth = ringWidth));
|
|
$effect(() => void (node.gap = gap));
|
|
|
|
// Register: composed inside an option → that option's children; else → root layer.
|
|
// `untrack` the writes (symmetry with OnionOption; keeps the effect single-run).
|
|
$effect(() => {
|
|
if (option) {
|
|
untrack(() => option.setChildLayer(node));
|
|
return () => untrack(() => option.setChildLayer(null));
|
|
}
|
|
untrack(() => menu?.setRootLayer(node));
|
|
return () => untrack(() => menu?.setRootLayer(null));
|
|
});
|
|
|
|
// Provide the layer registry for this level's options.
|
|
setOnionLayerRegistry({
|
|
registerOption: (n, seq) => node.insert(n, seq),
|
|
unregisterOption: (n) => node.remove(n)
|
|
});
|
|
</script>
|
|
|
|
{@render children?.()}
|