RepeatChildren.svelte 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. <script lang="ts">
  2. import type { Spec, UIElement } from "@json-render/core";
  3. import { getByPath } from "@json-render/core";
  4. import type { ComponentRegistry, ComponentRenderer } from "./renderer.js";
  5. import { getStateContext } from "./contexts/StateProvider.svelte";
  6. import RepeatScopeProvider from "./contexts/RepeatScopeProvider.svelte";
  7. import ElementRenderer from "./ElementRenderer.svelte";
  8. interface Props {
  9. element: UIElement;
  10. spec: Spec;
  11. registry: ComponentRegistry;
  12. loading?: boolean;
  13. fallback?: ComponentRenderer;
  14. }
  15. let { element, spec, registry, loading = false, fallback }: Props = $props();
  16. const stateCtx = getStateContext();
  17. // Get items from state
  18. let items = $derived(
  19. (getByPath(stateCtx.state, element.repeat!.statePath) as
  20. | unknown[]
  21. | undefined) ?? [],
  22. );
  23. </script>
  24. {#each items as itemValue, index (element.repeat?.key && typeof itemValue === "object" && itemValue !== null ? String((itemValue as any)[element.repeat.key] ?? index) : String(index))}
  25. {@const basePath = `${element.repeat!.statePath}/${index}`}
  26. {#if element.children}
  27. <RepeatScopeProvider item={itemValue} {index} {basePath}>
  28. {#each element.children as childKey (childKey)}
  29. {#if spec.elements[childKey]}
  30. <ElementRenderer
  31. element={spec.elements[childKey]}
  32. {spec}
  33. {registry}
  34. {loading}
  35. {fallback} />
  36. {:else if !loading}
  37. {console.warn(
  38. `[json-render] Missing element "${childKey}" referenced as child of "${element.type}". This element will not render.`,
  39. )}
  40. {/if}
  41. {/each}
  42. </RepeatScopeProvider>
  43. {/if}
  44. {/each}