mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-01-15 22:28:41 +00:00
progress
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
<script lang="ts">
|
||||
import Self from '$lib/components/map/layer-control/LayerTreeNode.svelte';
|
||||
import { Label } from '$lib/components/ui/label';
|
||||
import { Checkbox } from '$lib/components/ui/checkbox';
|
||||
import CollapsibleTreeNode from '$lib/components/collapsible-tree/CollapsibleTreeNode.svelte';
|
||||
import { type LayerTreeType } from '$lib/assets/layers';
|
||||
import { anySelectedLayer } from './utils.svelte';
|
||||
import { i18n } from '$lib/i18n.svelte';
|
||||
import { settings } from '$lib/logic/settings.svelte';
|
||||
|
||||
let {
|
||||
name,
|
||||
node,
|
||||
selected = '',
|
||||
onselect = () => {},
|
||||
multiple = false,
|
||||
checked = $bindable({}),
|
||||
}: {
|
||||
name: string;
|
||||
node: LayerTreeType;
|
||||
selected?: string;
|
||||
onselect?: (value: string) => void;
|
||||
multiple: boolean;
|
||||
checked: LayerTreeType;
|
||||
} = $props();
|
||||
|
||||
const { customLayers } = settings;
|
||||
|
||||
$effect.pre(() => {
|
||||
if (checked !== undefined) {
|
||||
Object.keys(node).forEach((id) => {
|
||||
if (!checked.hasOwnProperty(id)) {
|
||||
if (typeof node[id] == 'boolean') {
|
||||
checked[id] = false;
|
||||
} else {
|
||||
checked[id] = {};
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-[3px]">
|
||||
{#each Object.keys(node) as id}
|
||||
{#if typeof node[id] == 'boolean'}
|
||||
{#if node[id]}
|
||||
<div class="flex flex-row items-center gap-2 first:mt-0.5 h-4">
|
||||
{#if multiple}
|
||||
<Checkbox
|
||||
id="{name}-{id}"
|
||||
{name}
|
||||
value={id}
|
||||
bind:checked={checked[id]}
|
||||
class="scale-90"
|
||||
aria-label={i18n._(`layers.label.${id}`)}
|
||||
/>
|
||||
{:else}
|
||||
<input
|
||||
id="{name}-{id}"
|
||||
type="radio"
|
||||
{name}
|
||||
value={id}
|
||||
checked={selected === id}
|
||||
oninput={(e) => {
|
||||
if ((e.target as HTMLInputElement)?.checked) {
|
||||
onselect(id);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
<Label for="{name}-{id}" class="flex flex-row items-center gap-1">
|
||||
{#if customLayers.value.hasOwnProperty(id)}
|
||||
{customLayers.value[id].name}
|
||||
{:else}
|
||||
{i18n._(`layers.label.${id}`)}
|
||||
{/if}
|
||||
</Label>
|
||||
</div>
|
||||
{/if}
|
||||
{:else if anySelectedLayer(node[id])}
|
||||
<CollapsibleTreeNode {id}>
|
||||
{#snippet trigger()}
|
||||
<span>{i18n._(`layers.label.${id}`)}</span>
|
||||
{/snippet}
|
||||
{#snippet content()}
|
||||
<div class="ml-2">
|
||||
<Self
|
||||
node={node[id]}
|
||||
{name}
|
||||
{selected}
|
||||
{onselect}
|
||||
{multiple}
|
||||
bind:checked={checked[id]}
|
||||
/>
|
||||
</div>
|
||||
{/snippet}
|
||||
</CollapsibleTreeNode>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
@reference "../../../../app.css";
|
||||
|
||||
div :global(input[type='radio']) {
|
||||
@apply appearance-none;
|
||||
@apply w-4 h-4;
|
||||
@apply border-[1.5px] border-primary;
|
||||
@apply rounded-full;
|
||||
@apply ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2;
|
||||
@apply cursor-pointer;
|
||||
@apply checked:bg-primary;
|
||||
@apply checked:bg-clip-content;
|
||||
@apply checked:p-0.5;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user