Files
tools/vue/toolkit/src/composables/array/useArrayDifference/demo.vue
T
robonen aa2938cb34 refactor(toolkit): type source any with proper types
Genuinely type composable any usages (useStepper/useStorage/useForm/
createEventHook/useSorted/etc.) as proper generics/unknown; keep idiomatic
any-function and overload-impl signatures with comments; skipped test -> .todo.
2026-06-15 16:55:07 +07:00

98 lines
2.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { ref } from 'vue';
import { useArrayDifference } from './index';
interface Track {
id: number;
title: string;
}
const library: Track[] = [
{ id: 1, title: 'Midnight City' },
{ id: 2, title: 'Strobe' },
{ id: 3, title: 'Open Eye Signal' },
{ id: 4, title: 'Innerbloom' },
{ id: 5, title: 'Teardrop' },
{ id: 6, title: 'Resonance' },
];
const list = ref<Track[]>([...library]);
const playlist = ref<Track[]>([library[1], library[3]]);
const symmetric = ref(false);
// Compare tracks by their `id` key.
const diff = useArrayDifference(list, playlist, 'id', {
get symmetric() {
return symmetric.value;
},
});
function inPlaylist(track: Track) {
return playlist.value.some(t => t.id === track.id);
}
function toggle(track: Track) {
if (inPlaylist(track))
playlist.value = playlist.value.filter(t => t.id !== track.id);
else
playlist.value = [...playlist.value, track];
}
</script>
<template>
<div class="demo-stack max-w-md">
<div class="flex items-center justify-between">
<span class="demo-label">
Library tap to add / remove from playlist
</span>
<label class="inline-flex cursor-pointer items-center gap-2 text-sm text-fg-muted">
<input
v-model="symmetric"
type="checkbox"
class="size-4 cursor-pointer accent-accent"
>
Symmetric
</label>
</div>
<div class="grid grid-cols-2 gap-2">
<button
v-for="track in library"
:key="track.id"
class="inline-flex items-center justify-between gap-2 rounded-lg border px-3 py-2 text-sm font-medium transition active:scale-[0.98] cursor-pointer"
:class="inPlaylist(track)
? 'border-transparent bg-accent text-accent-fg hover:bg-accent-hover'
: 'border-border bg-bg-elevated text-fg hover:bg-bg-inset hover:border-border-strong'"
@click="toggle(track)"
>
<span class="truncate">{{ track.title }}</span>
<span class="shrink-0 text-xs opacity-70">{{ inPlaylist(track) ? '' : '+' }}</span>
</button>
</div>
<div class="demo-card p-4">
<div class="flex items-baseline justify-between">
<span class="demo-label">
{{ symmetric ? 'In exactly one (XOR)' : 'Not in playlist' }}
</span>
<span class="font-mono text-sm tabular-nums text-fg-muted">
{{ diff.length }}
</span>
</div>
<ul v-if="diff.length" class="mt-3 flex flex-wrap gap-2">
<li
v-for="track in diff"
:key="track.id"
class="demo-badge"
>
{{ track.title }}
</li>
</ul>
<p v-else class="mt-3 text-sm text-fg-subtle">
No difference every track matches.
</p>
</div>
</div>
</template>