Tabs.svelte 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. <script lang="ts">
  2. import { untrack } from "svelte";
  3. import type { Snippet } from "svelte";
  4. import { getBoundProp } from "@json-render/svelte";
  5. import type { BaseComponentProps } from "@json-render/svelte";
  6. import type { ShadcnProps } from "./catalog.js";
  7. import * as Tabs from "./ui/tabs/index.js";
  8. interface Props extends BaseComponentProps<ShadcnProps<"Tabs">> {
  9. children?: Snippet;
  10. }
  11. let { props, children, bindings, emit }: Props = $props();
  12. const tabs = $derived(props.tabs ?? []);
  13. let localValue = $state(untrack(() => props.defaultValue ?? tabs[0]?.value ?? ""));
  14. let activeValue = $state(untrack(() => localValue));
  15. let previousValue = $state(untrack(() => activeValue));
  16. const bound = getBoundProp<string>(
  17. () => props.value ?? undefined,
  18. () => bindings?.value,
  19. );
  20. $effect(() => {
  21. const current = bound.current ?? localValue ?? tabs[0]?.value ?? "";
  22. if (current !== activeValue) {
  23. activeValue = current;
  24. previousValue = current;
  25. }
  26. });
  27. $effect(() => {
  28. if (activeValue === previousValue) return;
  29. previousValue = activeValue;
  30. localValue = activeValue;
  31. bound.current = activeValue;
  32. emit("change");
  33. });
  34. </script>
  35. <Tabs.Root bind:value={activeValue}>
  36. <Tabs.List>
  37. {#each tabs as tab}
  38. <Tabs.Trigger value={tab.value}>{tab.label}</Tabs.Trigger>
  39. {/each}
  40. </Tabs.List>
  41. {@render children?.()}
  42. </Tabs.Root>