a]:font-medium [&>a]:underline [&>a]:decoration-dashed [&>a]:decoration-primary/50 [&>a]:underline-offset-2'
+ )}
+>
+
+ {@render children()}
+
diff --git a/docs/src/lib/components/Code.svelte b/docs/src/lib/components/Code.svelte
new file mode 100644
index 000000000..6da6eddb5
--- /dev/null
+++ b/docs/src/lib/components/Code.svelte
@@ -0,0 +1,175 @@
+
+
+
+
+ onItemClick?.()}
+ />
+{/snippet}
diff --git a/docs/src/lib/components/Example.svelte b/docs/src/lib/components/Example.svelte
new file mode 100644
index 000000000..ff895f878
--- /dev/null
+++ b/docs/src/lib/components/Example.svelte
@@ -0,0 +1,382 @@
+
+
+
+ {#if example}
+
+
+ {#if isVisible}
+
+
+ {#snippet failed(error, reset)}
+
+
+ Example error{#if component && name}: {component}/{name}{/if}
+
+
{error}
+
Retry
+
+ {/snippet}
+ {#snippet pending()}
+
+ Loading...
+
+ {/snippet}
+
+ {:else}
+
+ {/if}
+
+ {#if canResize}
+
{
+ const newWidth = (containerWidth ?? containerEl?.offsetWidth ?? 0) + e.detail.dx;
+ if (newWidth >= minWidth) {
+ containerWidth = newWidth;
+ }
+ }
+ }}
+ >
+
+
+ {/if}
+
+
+
+ {#if showCode}
+
+
+
+ {/if}
+
+ {#if variant === 'default'}
+
+ {#if example.source}
+
(showCode = !showCode)}
+ >
+ {showCode ? 'Hide' : ''} Code
+
+ {/if}
+
+ {#if data}
+
+
+ Data
+
+
+
+
+
+
+
+ getDataAsString(data)}
+ variant="fill-light"
+ color="primary"
+ />
+
+
+
+
+
+
+ Close
+
+
+
+ {/if}
+
+ {#if page.params.example == null && component && name}
+
+
+ View
+
+ {/if}
+
+ {#if component && name}
+
openInStackBlitz(component, name)}
+ >
+ Edit
+
+ {/if}
+
+
+
+ Export
+
+ downloadImage(containerEl!, { filename: name ?? component })}
+ >
+ Export as PNG
+
+ {#if settings.layer !== 'canvas'}
+
+ Export as SVG
+
+ {/if}
+
+
+
+
+ {/if}
+ {:else}
+
+ Example `{path ?? name}`
+ {#if component && !path}
+ for `{component}`
+ {/if}
+ not found.
+
+ {/if}
+
+
+{#if svgUnavailable}
+
+ (svgUnavailable = false)}
+ />
+
+{/if}
diff --git a/docs/src/lib/components/ExampleLink.svelte b/docs/src/lib/components/ExampleLink.svelte
new file mode 100644
index 000000000..2e35f1bd5
--- /dev/null
+++ b/docs/src/lib/components/ExampleLink.svelte
@@ -0,0 +1,74 @@
+
+
+
+ {#snippet image()}
+
+ {/snippet}
+
+ {#snippet label()}
+
+
+ {#if showComponent}
+ {component}
+
+ {/if}
+ {title ?? example.replaceAll('-', ' ')}
+ {/snippet}
+
diff --git a/docs/src/lib/components/ExampleListing.svelte b/docs/src/lib/components/ExampleListing.svelte
new file mode 100644
index 000000000..ee428b8db
--- /dev/null
+++ b/docs/src/lib/components/ExampleListing.svelte
@@ -0,0 +1,163 @@
+
+
+{#if hasContent}
+
+
{title}
+
+ {#if viewAllHref && catalog.examples?.length}
+
View all
+ {/if}
+
+
+ {#snippet prepend()}
+
+ {/snippet}
+
+
+
+ (columnCount = Math.min(5, columnCount + 1))}
+ variant="fill-outline"
+ class="size-8 border-surface-content/30 pt-1"
+ disabled={columnCount >= 5}
+ />
+ (columnCount = Math.max(1, columnCount - 1))}
+ variant="fill-outline"
+ class="size-8 border-surface-content/30 pt-1"
+ disabled={columnCount <= 1}
+ />
+
+
+
+
+ {#if examples.length}
+
+ {#each examples as example (example.name)}
+
+ {/each}
+
+ {:else if catalog.examples?.length}
+ No examples match your filter.
+ {/if}
+
+ {#if uniqueUsage.length}
+ {#if examples.length}
+
+ {showDetails ? 'show less' : 'show more'}...
+
+
+ {#each uniqueUsage as usage (`${usage.component}::${usage.example}`)}
+
+ {/each}
+
+
+
+ {:else if catalog.examples?.length === 0}
+
+
+ {#each uniqueUsage as usage (`${usage.component}::${usage.example}`)}
+
+ {/each}
+
+ {:else if catalog.usage?.length}
+
+ No additional usage examples match your filter.
+
+ {/if}
+ {/if}
+{/if}
diff --git a/docs/src/lib/components/ExampleScreenshot.svelte b/docs/src/lib/components/ExampleScreenshot.svelte
new file mode 100644
index 000000000..3c8b90a93
--- /dev/null
+++ b/docs/src/lib/components/ExampleScreenshot.svelte
@@ -0,0 +1,70 @@
+
+
+
+ {#if hasError && fallbackIcon}
+ {@const FallbackIcon = fallbackIcon}
+
+
+
+ {:else if !hasError}
+ {#each ['light', 'dark'] as mode (mode)}
+ {#each sizes as size (size.width)}
+
(hasError = true)}
+ />
+ {/each}
+ {/each}
+ {/if}
+
diff --git a/docs/src/lib/components/ImageLink.svelte b/docs/src/lib/components/ImageLink.svelte
new file mode 100644
index 000000000..2f060b0a6
--- /dev/null
+++ b/docs/src/lib/components/ImageLink.svelte
@@ -0,0 +1,61 @@
+
+
+
+ {#if image}
+
+ {@render image()}
+
+ {/if}
+
+ {#if label && variant !== 'screenshot-only'}
+
+
+ {@render label()}
+
+
+
+
+ {/if}
+
diff --git a/docs/src/lib/components/Json.svelte b/docs/src/lib/components/Json.svelte
new file mode 100644
index 000000000..7d6335c01
--- /dev/null
+++ b/docs/src/lib/components/Json.svelte
@@ -0,0 +1,36 @@
+
+
+
+
+
diff --git a/docs/src/lib/components/LoadingPlaceholder.svelte b/docs/src/lib/components/LoadingPlaceholder.svelte
new file mode 100644
index 000000000..fb31a5526
--- /dev/null
+++ b/docs/src/lib/components/LoadingPlaceholder.svelte
@@ -0,0 +1,8 @@
+
+
+
diff --git a/docs/src/lib/components/Logo.svelte b/docs/src/lib/components/Logo.svelte
new file mode 100644
index 000000000..5c3a163c4
--- /dev/null
+++ b/docs/src/lib/components/Logo.svelte
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/lib/components/OpenWithButton.svelte b/docs/src/lib/components/OpenWithButton.svelte
new file mode 100644
index 000000000..48cf7e838
--- /dev/null
+++ b/docs/src/lib/components/OpenWithButton.svelte
@@ -0,0 +1,198 @@
+
+
+
+ {
+ const md = await fetch(`${pageUrl}/llms.txt`).then((res) => res.text());
+ copy(md);
+ }}
+ >
+
+ {#key showButtonCopied}
+
+ {showButtonCopied ? 'Copied!' : 'Copy Page'}
+
+ {/key}
+
+
+
+
+
+
+
+
+ {#each llms as llm (llm.label)}
+ {#if llm.lineBreakBefore}
+
+ {/if}
+ {
+ toggleOff();
+ llm.fn?.();
+ }}
+ >
+
+ {llm.label}
+
+ {/each}
+
+
+
+
+
+ (openSourceModal = false)}
+ class="max-h-[98dvh] md:max-h-[90dvh] max-w-[98vw] md:max-w-[90vw] grid grid-rows-[auto_1fr_auto]"
+>
+
+
+
Source
+
{metadata?.sourceUrl}
+
+
+ {#if metadata?.sourceUrl}
+
+ View on Github
+
+ {/if}
+
+
+
+
+
+
+
+ Close
+
+
+
+ (openMarkdownModal = false)}
+ class="max-h-[98dvh] md:max-h-[90dvh] max-w-[98vw] md:max-w-[90vw] grid grid-rows-[auto_1fr_auto]"
+>
+
+
+
Page Markdown
+
{pageUrl}/llms.txt
+
+
+
+ Open Raw
+
+
+
+
+
+
+
+
+ Close
+
+
diff --git a/docs/src/lib/components/PromiseExample.svelte b/docs/src/lib/components/PromiseExample.svelte
new file mode 100644
index 000000000..accf681dc
--- /dev/null
+++ b/docs/src/lib/components/PromiseExample.svelte
@@ -0,0 +1,24 @@
+
+
+{#await componentPromise}
+ Loading component...
+{:then module}
+
+{:catch error}
+ Error loading component: {error.message}
+{/await}
+
+{#await sourcePromise}
+ Loading source...
+{:then source}
+
+{:catch error}
+ Error loading source: {error.message}
+{/await}
diff --git a/docs/src/lib/components/RelatedLink.svelte b/docs/src/lib/components/RelatedLink.svelte
new file mode 100644
index 000000000..4aeaf5d70
--- /dev/null
+++ b/docs/src/lib/components/RelatedLink.svelte
@@ -0,0 +1,50 @@
+
+
+{#if type === 'component'}
+
+{:else}
+
+ {name}
+
+{/if}
diff --git a/docs/src/lib/components/SourceExample.svelte b/docs/src/lib/components/SourceExample.svelte
new file mode 100644
index 000000000..db7ad32c3
--- /dev/null
+++ b/docs/src/lib/components/SourceExample.svelte
@@ -0,0 +1,7 @@
+
+
+{@render children?.()}
diff --git a/docs/src/lib/components/Stats.svelte b/docs/src/lib/components/Stats.svelte
new file mode 100644
index 000000000..a1a2dcf6d
--- /dev/null
+++ b/docs/src/lib/components/Stats.svelte
@@ -0,0 +1,100 @@
+
+
+{#if query.loading || query.error || !query.current}
+
+{:else}
+
+{/if}
diff --git a/docs/src/lib/components/Step.svelte b/docs/src/lib/components/Step.svelte
new file mode 100644
index 000000000..51a1696a6
--- /dev/null
+++ b/docs/src/lib/components/Step.svelte
@@ -0,0 +1,36 @@
+
+
+
+
+
+ {@html title}
+
+ {@render children?.()}
+
+
+
diff --git a/docs/src/lib/components/Steps.svelte b/docs/src/lib/components/Steps.svelte
new file mode 100644
index 000000000..162915b96
--- /dev/null
+++ b/docs/src/lib/components/Steps.svelte
@@ -0,0 +1,9 @@
+
+
+
+ {@render children?.()}
+
diff --git a/docs/src/lib/components/TableOfContents.svelte b/docs/src/lib/components/TableOfContents.svelte
new file mode 100644
index 000000000..30d6a872b
--- /dev/null
+++ b/docs/src/lib/components/TableOfContents.svelte
@@ -0,0 +1,78 @@
+
+
+{#if items.length}
+
+
+
+{/if}
diff --git a/docs/src/lib/components/Tabs.svelte b/docs/src/lib/components/Tabs.svelte
new file mode 100644
index 000000000..071a9e596
--- /dev/null
+++ b/docs/src/lib/components/Tabs.svelte
@@ -0,0 +1,62 @@
+
+
+
+ {#each keys as key, v}
+ {@const isActive = value === v}
+ {@const Icon = icons?.[v] ?? null}
+ (value = v)}
+ selected={isActive}
+ >{#if Icon} {:else}{/if}{key}
+ {/each}
+
+
+ {@render content?.(value)}
+
+
+
diff --git a/docs/src/lib/components/ViewSourceButton.svelte b/docs/src/lib/components/ViewSourceButton.svelte
new file mode 100644
index 000000000..140c78850
--- /dev/null
+++ b/docs/src/lib/components/ViewSourceButton.svelte
@@ -0,0 +1,53 @@
+
+
+{#if source}
+
+ {label}
+
+
+
+
+ {#if href}
+
+ View on Github
+
+ {/if}
+
+
+
+
+
+
+
+ Close
+
+
+
+{:else if href}
+
+
+ {label}
+
+
+{/if}
diff --git a/docs/src/lib/components/controls/AnnotationRangePointLineControls.svelte b/docs/src/lib/components/controls/AnnotationRangePointLineControls.svelte
new file mode 100644
index 000000000..4bd05b996
--- /dev/null
+++ b/docs/src/lib/components/controls/AnnotationRangePointLineControls.svelte
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+ {placement}
+
+
+
+
+
+ {#each placementOptions as option (option)}
+ (placement = option)}
+ >
+ {option}
+
+ {/each}
+
+
+
+
+
+ {#if radius !== undefined}
+
+ {/if}
+
diff --git a/docs/src/lib/components/controls/ArcControls.svelte b/docs/src/lib/components/controls/ArcControls.svelte
new file mode 100644
index 000000000..ec5d2e3b3
--- /dev/null
+++ b/docs/src/lib/components/controls/ArcControls.svelte
@@ -0,0 +1,17 @@
+
+
+
+
+ {#if segments !== undefined}
+
+ {/if}
+
diff --git a/docs/src/lib/components/controls/ArcPlaygroundControls.svelte b/docs/src/lib/components/controls/ArcPlaygroundControls.svelte
new file mode 100644
index 000000000..b350775fe
--- /dev/null
+++ b/docs/src/lib/components/controls/ArcPlaygroundControls.svelte
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/AreaPlaygroundControls.svelte b/docs/src/lib/components/controls/AreaPlaygroundControls.svelte
new file mode 100644
index 000000000..a13f97cc3
--- /dev/null
+++ b/docs/src/lib/components/controls/AreaPlaygroundControls.svelte
@@ -0,0 +1,60 @@
+
+
+
+
+
+ {#if includeShowTween}
+
+
+
+
+
+
+
+
+
+ {/if}
+
diff --git a/docs/src/lib/components/controls/AxisControls.svelte b/docs/src/lib/components/controls/AxisControls.svelte
new file mode 100644
index 000000000..c225c9f42
--- /dev/null
+++ b/docs/src/lib/components/controls/AxisControls.svelte
@@ -0,0 +1,23 @@
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/BarsControls.svelte b/docs/src/lib/components/controls/BarsControls.svelte
new file mode 100644
index 000000000..61d955fed
--- /dev/null
+++ b/docs/src/lib/components/controls/BarsControls.svelte
@@ -0,0 +1,19 @@
+
+
+
+
+
+ Grouped
+ Stacked
+ Grouped & Stacked
+
+
+
diff --git a/docs/src/lib/components/controls/ColorRampControls.svelte b/docs/src/lib/components/controls/ColorRampControls.svelte
new file mode 100644
index 000000000..886c438f7
--- /dev/null
+++ b/docs/src/lib/components/controls/ColorRampControls.svelte
@@ -0,0 +1,14 @@
+
+
+
+ Steps:
+
+
diff --git a/docs/src/lib/components/controls/DagreControls.svelte b/docs/src/lib/components/controls/DagreControls.svelte
new file mode 100644
index 000000000..b8aaf75ff
--- /dev/null
+++ b/docs/src/lib/components/controls/DagreControls.svelte
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/DagrePlaygroundControls.svelte b/docs/src/lib/components/controls/DagrePlaygroundControls.svelte
new file mode 100644
index 000000000..54aa180cb
--- /dev/null
+++ b/docs/src/lib/components/controls/DagrePlaygroundControls.svelte
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+ (showSettings = !showSettings)}
+ {id}
+ size="md"
+ />
+
+
diff --git a/docs/src/lib/components/controls/ForceGraphPlaygroundControls.svelte b/docs/src/lib/components/controls/ForceGraphPlaygroundControls.svelte
new file mode 100644
index 000000000..7a15f556a
--- /dev/null
+++ b/docs/src/lib/components/controls/ForceGraphPlaygroundControls.svelte
@@ -0,0 +1,200 @@
+
+
+
+
+
+ Static
+
+
+ Stopped
+
+
+
+
+ {#if config.running}
+
+ {/if}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/ForceSimluationControls2.svelte b/docs/src/lib/components/controls/ForceSimluationControls2.svelte
new file mode 100644
index 000000000..94c7272eb
--- /dev/null
+++ b/docs/src/lib/components/controls/ForceSimluationControls2.svelte
@@ -0,0 +1,18 @@
+
+
+
+
+
+ Sticky
+
+
+
+
diff --git a/docs/src/lib/components/controls/ForceSimulationControls.svelte b/docs/src/lib/components/controls/ForceSimulationControls.svelte
new file mode 100644
index 000000000..bc671fd4a
--- /dev/null
+++ b/docs/src/lib/components/controls/ForceSimulationControls.svelte
@@ -0,0 +1,18 @@
+
+
+
+
+
+ Group
+ Clump
+
+
+
diff --git a/docs/src/lib/components/controls/ForceTextControls.svelte b/docs/src/lib/components/controls/ForceTextControls.svelte
new file mode 100644
index 000000000..e3593d748
--- /dev/null
+++ b/docs/src/lib/components/controls/ForceTextControls.svelte
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/GeoCircleEarthquakeControls.svelte b/docs/src/lib/components/controls/GeoCircleEarthquakeControls.svelte
new file mode 100644
index 000000000..41397def4
--- /dev/null
+++ b/docs/src/lib/components/controls/GeoCircleEarthquakeControls.svelte
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+ Start
+ Stop
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/GeoCirclePlaygroundControls.svelte b/docs/src/lib/components/controls/GeoCirclePlaygroundControls.svelte
new file mode 100644
index 000000000..3bf3a2f4e
--- /dev/null
+++ b/docs/src/lib/components/controls/GeoCirclePlaygroundControls.svelte
@@ -0,0 +1,74 @@
+
+
+
+
+
+ Single
+ Multi
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/GeoContextPlaygroundControls.svelte b/docs/src/lib/components/controls/GeoContextPlaygroundControls.svelte
new file mode 100644
index 000000000..5a4115eba
--- /dev/null
+++ b/docs/src/lib/components/controls/GeoContextPlaygroundControls.svelte
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/GeoPathGlobeControls.svelte b/docs/src/lib/components/controls/GeoPathGlobeControls.svelte
new file mode 100644
index 000000000..18033b641
--- /dev/null
+++ b/docs/src/lib/components/controls/GeoPathGlobeControls.svelte
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+ {#if isPlaying && selectedFeature}
+
+ {selectedFeature?.properties.name ?? ''}
+
+ {/if}
+
diff --git a/docs/src/lib/components/controls/GeoPathGlobeControls2.svelte b/docs/src/lib/components/controls/GeoPathGlobeControls2.svelte
new file mode 100644
index 000000000..cc8727ef4
--- /dev/null
+++ b/docs/src/lib/components/controls/GeoPathGlobeControls2.svelte
@@ -0,0 +1,46 @@
+
+
+
+ {#if minArea !== undefined}
+
+
+
+
+ {/if}
+
+
+
+ Start
+ Stop
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/GeoPathProjectionControls.svelte b/docs/src/lib/components/controls/GeoPathProjectionControls.svelte
new file mode 100644
index 000000000..e95ad7e74
--- /dev/null
+++ b/docs/src/lib/components/controls/GeoPathProjectionControls.svelte
@@ -0,0 +1,21 @@
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/GeoPathStatesControls.svelte b/docs/src/lib/components/controls/GeoPathStatesControls.svelte
new file mode 100644
index 000000000..b15657055
--- /dev/null
+++ b/docs/src/lib/components/controls/GeoPathStatesControls.svelte
@@ -0,0 +1,36 @@
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/GeoPathSubmarineControls.svelte b/docs/src/lib/components/controls/GeoPathSubmarineControls.svelte
new file mode 100644
index 000000000..019ffd692
--- /dev/null
+++ b/docs/src/lib/components/controls/GeoPathSubmarineControls.svelte
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+ Start
+ Stop
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/GeoPathTimezonesControls.svelte b/docs/src/lib/components/controls/GeoPathTimezonesControls.svelte
new file mode 100644
index 000000000..061a81712
--- /dev/null
+++ b/docs/src/lib/components/controls/GeoPathTimezonesControls.svelte
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/GeoPointControls.svelte b/docs/src/lib/components/controls/GeoPointControls.svelte
new file mode 100644
index 000000000..96d599813
--- /dev/null
+++ b/docs/src/lib/components/controls/GeoPointControls.svelte
@@ -0,0 +1,21 @@
+
+
+
+
+
+ quadtree
+ voronoi
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/GeoTileControls.svelte b/docs/src/lib/components/controls/GeoTileControls.svelte
new file mode 100644
index 000000000..c1e6c8aa8
--- /dev/null
+++ b/docs/src/lib/components/controls/GeoTileControls.svelte
@@ -0,0 +1,144 @@
+
+
+
+
+ e.stopPropagation()} role="none">
+
2x
+
+
+
+
diff --git a/docs/src/lib/components/controls/GraticuleControls.svelte b/docs/src/lib/components/controls/GraticuleControls.svelte
new file mode 100644
index 000000000..9f96f9598
--- /dev/null
+++ b/docs/src/lib/components/controls/GraticuleControls.svelte
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/HistogramControls.svelte b/docs/src/lib/components/controls/HistogramControls.svelte
new file mode 100644
index 000000000..fa739d9ed
--- /dev/null
+++ b/docs/src/lib/components/controls/HistogramControls.svelte
@@ -0,0 +1,100 @@
+
+
+{#if dateRange !== undefined || thresholds !== undefined || interval !== undefined}
+
+ {#if dateRange !== undefined}
+
+ {/if}
+ {#if thresholds !== undefined}
+
+ {/if}
+ {#if interval !== undefined}
+
+ {/if}
+
+{/if}
+
+{#if selectedGenerator !== undefined || randomCount !== undefined}
+
+ {#if selectedGenerator !== undefined}
+ {
+ switch (e.detail.value) {
+ case 'normal':
+ random = randomNormal();
+ break;
+ case 'uniform':
+ random = randomUniform();
+ break;
+ case 'integer':
+ random = randomInt(1, 10);
+ break;
+ case 'logNormal':
+ random = randomLogNormal();
+ break;
+ case 'exponential':
+ random = randomExponential(10);
+ break;
+ case 'bates':
+ random = randomBates(10);
+ break;
+ }
+ }}
+ />
+ {/if}
+
+ {#if randomCount !== undefined}
+
+ {/if}
+
+{/if}
diff --git a/docs/src/lib/components/controls/LineChartControls.svelte b/docs/src/lib/components/controls/LineChartControls.svelte
new file mode 100644
index 000000000..1144c2104
--- /dev/null
+++ b/docs/src/lib/components/controls/LineChartControls.svelte
@@ -0,0 +1,45 @@
+
+
+
+ {#if !config.isListening}
+
+ Start Microphone
+
+ {:else}
+
+ Stop Microphone
+
+ {/if}
+ {#if config.error}
+ {config.error}
+ {/if}
+
diff --git a/docs/src/lib/components/controls/LinkControls.svelte b/docs/src/lib/components/controls/LinkControls.svelte
new file mode 100644
index 000000000..4dfe76133
--- /dev/null
+++ b/docs/src/lib/components/controls/LinkControls.svelte
@@ -0,0 +1,77 @@
+
+
+
+
+ {#if type === 'd3'}
+
+ {/if}
+ {#if type === 'beveled' || type === 'rounded'}
+
+ {/if}
+ {#if type === 'swoop'}
+
+ {/if}
+
+
+
+ {#if type === 'd3'}
+
+ {/if}
+
+
diff --git a/docs/src/lib/components/controls/MarkerControls.svelte b/docs/src/lib/components/controls/MarkerControls.svelte
new file mode 100644
index 000000000..40969ea0c
--- /dev/null
+++ b/docs/src/lib/components/controls/MarkerControls.svelte
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+ {#if config.markerStart !== undefined}
+
+
+
+ {/if}
+ {#if config.markerMid !== undefined}
+
+
+
+ {/if}
+ {#if config.markerEnd !== undefined}
+
+
+
+ {/if}
+
+
+
+
diff --git a/docs/src/lib/components/controls/MarkerControls2.svelte b/docs/src/lib/components/controls/MarkerControls2.svelte
new file mode 100644
index 000000000..ea74fecd8
--- /dev/null
+++ b/docs/src/lib/components/controls/MarkerControls2.svelte
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/MotionPathControls.svelte b/docs/src/lib/components/controls/MotionPathControls.svelte
new file mode 100644
index 000000000..cc5b6e41a
--- /dev/null
+++ b/docs/src/lib/components/controls/MotionPathControls.svelte
@@ -0,0 +1,52 @@
+
+
+
diff --git a/docs/src/lib/components/controls/PackControls.svelte b/docs/src/lib/components/controls/PackControls.svelte
new file mode 100644
index 000000000..2927aaf5d
--- /dev/null
+++ b/docs/src/lib/components/controls/PackControls.svelte
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+ Parent
+ Depth
+
+
+
diff --git a/docs/src/lib/components/controls/PartitionControls.svelte b/docs/src/lib/components/controls/PartitionControls.svelte
new file mode 100644
index 000000000..8dc6d7a0f
--- /dev/null
+++ b/docs/src/lib/components/controls/PartitionControls.svelte
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+ Yes
+ No
+
+
+
+
+ Yes
+ No
+
+
+
+
+ Children
+ Depth
+ Parent
+
+
+
+
+{#if isFiltered !== undefined}
+
+
+
+
+
+{/if}
diff --git a/docs/src/lib/components/controls/PieChartControls.svelte b/docs/src/lib/components/controls/PieChartControls.svelte
new file mode 100644
index 000000000..a4e3d250c
--- /dev/null
+++ b/docs/src/lib/components/controls/PieChartControls.svelte
@@ -0,0 +1,15 @@
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/PolygonControls.svelte b/docs/src/lib/components/controls/PolygonControls.svelte
new file mode 100644
index 000000000..82fca1e7d
--- /dev/null
+++ b/docs/src/lib/components/controls/PolygonControls.svelte
@@ -0,0 +1,35 @@
+
+
+
+ {#if starInset !== undefined}
+
+ {/if}
+ {#if rotate !== undefined}
+
+ {/if}
+ {#if cornerRadius !== undefined}
+
+ {/if}
+
diff --git a/docs/src/lib/components/controls/PolygonPlaygroundControls.svelte b/docs/src/lib/components/controls/PolygonPlaygroundControls.svelte
new file mode 100644
index 000000000..7c5943c10
--- /dev/null
+++ b/docs/src/lib/components/controls/PolygonPlaygroundControls.svelte
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/SankeyControls.svelte b/docs/src/lib/components/controls/SankeyControls.svelte
new file mode 100644
index 000000000..8a75c6b2b
--- /dev/null
+++ b/docs/src/lib/components/controls/SankeyControls.svelte
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/SplineControls.svelte b/docs/src/lib/components/controls/SplineControls.svelte
new file mode 100644
index 000000000..683b80866
--- /dev/null
+++ b/docs/src/lib/components/controls/SplineControls.svelte
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+ {#if config.motion !== undefined}
+
+
+
+
+
+
+ tween
+ draw
+ none
+
+
+ {/if}
+
diff --git a/docs/src/lib/components/controls/SplineControls2.svelte b/docs/src/lib/components/controls/SplineControls2.svelte
new file mode 100644
index 000000000..1213dc378
--- /dev/null
+++ b/docs/src/lib/components/controls/SplineControls2.svelte
@@ -0,0 +1,60 @@
+
+
+
+
+
+ {#if config.motion !== undefined}
+
+
+
+
+
+
+ tween
+ draw
+ none
+
+
+ {/if}
+
diff --git a/docs/src/lib/components/controls/SunburstControls.svelte b/docs/src/lib/components/controls/SunburstControls.svelte
new file mode 100644
index 000000000..fa5e16e12
--- /dev/null
+++ b/docs/src/lib/components/controls/SunburstControls.svelte
@@ -0,0 +1,18 @@
+
+
+
+
+
+ Parent
+ Depth
+
+
+
diff --git a/docs/src/lib/components/controls/TextPlaygroundControls.svelte b/docs/src/lib/components/controls/TextPlaygroundControls.svelte
new file mode 100644
index 000000000..734b1d51c
--- /dev/null
+++ b/docs/src/lib/components/controls/TextPlaygroundControls.svelte
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ start
+ middle
+ end
+
+
+
+
+
+ start
+ middle
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#if config.truncate}
+
+
+
+ start
+ middle
+ end
+
+
+
+ {/if}
+
+
diff --git a/docs/src/lib/components/controls/TextTruncateControls.svelte b/docs/src/lib/components/controls/TextTruncateControls.svelte
new file mode 100644
index 000000000..b78a222ea
--- /dev/null
+++ b/docs/src/lib/components/controls/TextTruncateControls.svelte
@@ -0,0 +1,17 @@
+
+
+
+
+ start
+ middle
+ end
+
+
diff --git a/docs/src/lib/components/controls/TooltipContextControls.svelte b/docs/src/lib/components/controls/TooltipContextControls.svelte
new file mode 100644
index 000000000..950a3afe7
--- /dev/null
+++ b/docs/src/lib/components/controls/TooltipContextControls.svelte
@@ -0,0 +1,98 @@
+
+
+
+
+
+ options.map((x) => x.label).join(', ')}
+ />
+
+
+
+ {
+ switch (e.detail.value) {
+ case 'off':
+ settings.snapToDataX = false;
+ settings.snapToDataY = false;
+ break;
+ case 'x-only':
+ settings.snapToDataX = true;
+ settings.snapToDataY = false;
+ break;
+ case 'y-only':
+ settings.snapToDataX = false;
+ settings.snapToDataY = true;
+ break;
+ case 'both':
+ settings.snapToDataX = true;
+ settings.snapToDataY = true;
+ break;
+ }
+ }}
+ options={[
+ { label: 'off', value: 'off' },
+ { label: 'x-only', value: 'x-only' },
+ { label: 'y-only', value: 'y-only' },
+ { label: 'both', value: 'both' }
+ ]}
+ />
+
diff --git a/docs/src/lib/components/controls/TooltipContextControls2.svelte b/docs/src/lib/components/controls/TooltipContextControls2.svelte
new file mode 100644
index 000000000..ec9cab2c3
--- /dev/null
+++ b/docs/src/lib/components/controls/TooltipContextControls2.svelte
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+ {anchor}
+
+
+
+
+
+ {#each anchorOptions as option}
+ (anchor = option)}
+ >
+ {option}
+
+ {/each}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/TrailControls.svelte b/docs/src/lib/components/controls/TrailControls.svelte
new file mode 100644
index 000000000..de4dd728e
--- /dev/null
+++ b/docs/src/lib/components/controls/TrailControls.svelte
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+ {#if config.motion !== undefined}
+
+
+
+
+
+
+ none
+ tween
+
+
+ {/if}
+
diff --git a/docs/src/lib/components/controls/TransformContextControls.svelte b/docs/src/lib/components/controls/TransformContextControls.svelte
new file mode 100644
index 000000000..97c034759
--- /dev/null
+++ b/docs/src/lib/components/controls/TransformContextControls.svelte
@@ -0,0 +1,241 @@
+
+
+
+
+
+ {
+ // Stop from propagating to TransformContext
+ e.stopPropagation();
+ }}
+>
+ {#if show.includes('zoomIn')}
+
+ chart.transform.zoomIn()}
+ {size}
+ class="text-surface-content p-2"
+ />
+
+ {/if}
+
+ {#if show.includes('zoomOut')}
+
+ chart.transform.zoomOut()}
+ {size}
+ class="text-surface-content p-2"
+ />
+
+ {/if}
+
+ {#if show.includes('center')}
+
+ chart.transform.translateCenter()}
+ {size}
+ class="text-surface-content p-2"
+ />
+
+ {/if}
+
+ {#if show.includes('reset')}
+
+ chart.transform.reset()}
+ {size}
+ class="text-surface-content p-2"
+ />
+
+ {/if}
+
+ {#if show.includes('scrollMode')}
+
+ (chart.transform.scrollMode = e.detail.value)}
+ class="text-surface-content"
+ >
+
+ {#key value}
+
+ {/key}
+
+
+
+ {/if}
+
+
+
diff --git a/docs/src/lib/components/controls/TransformContextPlaygroundControls.svelte b/docs/src/lib/components/controls/TransformContextPlaygroundControls.svelte
new file mode 100644
index 000000000..396c1e1c5
--- /dev/null
+++ b/docs/src/lib/components/controls/TransformContextPlaygroundControls.svelte
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/TreeControls.svelte b/docs/src/lib/components/controls/TreeControls.svelte
new file mode 100644
index 000000000..67a7ea29e
--- /dev/null
+++ b/docs/src/lib/components/controls/TreeControls.svelte
@@ -0,0 +1,123 @@
+
+
+
+ {#if datasetOptions}
+
+ {/if}
+
+
+
+ Horizontal
+ Vertical
+ Radial
+
+
+
+
+
+ Chart
+ Node
+
+
+
+
+
+
+
+ {#if config.type === 'd3'}
+
+ {/if}
+
+ {#if config.type === 'beveled' || config.type === 'rounded'}
+
+ {/if}
+
+ {#if config.type === 'swoop'}
+
+ {/if}
+
+
+
+
+
+
+ {#if config.orientation === 'radial'}
+
+ {:else}
+
+ {/if}
+
diff --git a/docs/src/lib/components/controls/TreemapControls.svelte b/docs/src/lib/components/controls/TreemapControls.svelte
new file mode 100644
index 000000000..9335b23e1
--- /dev/null
+++ b/docs/src/lib/components/controls/TreemapControls.svelte
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+ Squarify
+ Resquarify
+ Binary
+ Slice
+ Dice
+ Slice / Dice
+
+
+
+
+ No
+ Yes
+
+
+
+
+ Children
+ Depth
+ Parent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#if config.isFiltered !== undefined}
+
+
+
+
+
+ {/if}
+
diff --git a/docs/src/lib/components/controls/VoronoiControls.svelte b/docs/src/lib/components/controls/VoronoiControls.svelte
new file mode 100644
index 000000000..db3a9705a
--- /dev/null
+++ b/docs/src/lib/components/controls/VoronoiControls.svelte
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/fields/CurveMenuField.svelte b/docs/src/lib/components/controls/fields/CurveMenuField.svelte
new file mode 100644
index 000000000..272a494b9
--- /dev/null
+++ b/docs/src/lib/components/controls/fields/CurveMenuField.svelte
@@ -0,0 +1,46 @@
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/fields/GroupedStackedComboField.svelte b/docs/src/lib/components/controls/fields/GroupedStackedComboField.svelte
new file mode 100644
index 000000000..61d955fed
--- /dev/null
+++ b/docs/src/lib/components/controls/fields/GroupedStackedComboField.svelte
@@ -0,0 +1,19 @@
+
+
+
+
+
+ Grouped
+ Stacked
+ Grouped & Stacked
+
+
+
diff --git a/docs/src/lib/components/controls/fields/OscilloscopeField.svelte b/docs/src/lib/components/controls/fields/OscilloscopeField.svelte
new file mode 100644
index 000000000..9f6c85507
--- /dev/null
+++ b/docs/src/lib/components/controls/fields/OscilloscopeField.svelte
@@ -0,0 +1,47 @@
+
+
+
+ {#if !isListening}
+
+ Start Microphone
+
+ {:else}
+
+ Stop Microphone
+
+ {/if}
+ {#if error}
+ {error}
+ {/if}
+
diff --git a/docs/src/lib/components/controls/fields/PathDataMenuField.svelte b/docs/src/lib/components/controls/fields/PathDataMenuField.svelte
new file mode 100644
index 000000000..448cefb55
--- /dev/null
+++ b/docs/src/lib/components/controls/fields/PathDataMenuField.svelte
@@ -0,0 +1,80 @@
+
+
+
+
+
diff --git a/docs/src/lib/components/controls/fields/RadialField.svelte b/docs/src/lib/components/controls/fields/RadialField.svelte
new file mode 100644
index 000000000..a639baffb
--- /dev/null
+++ b/docs/src/lib/components/controls/fields/RadialField.svelte
@@ -0,0 +1,19 @@
+
+
+
+
+
+ Linear
+ CatmullRom
+
+
+
diff --git a/docs/src/lib/components/controls/fields/ShowField.svelte b/docs/src/lib/components/controls/fields/ShowField.svelte
new file mode 100644
index 000000000..3360f3e9c
--- /dev/null
+++ b/docs/src/lib/components/controls/fields/ShowField.svelte
@@ -0,0 +1,44 @@
+
+
+{#if !inline}
+
+
+
+
+
+{:else}
+
+
+
+
+
+{/if}
diff --git a/docs/src/lib/context.ts b/docs/src/lib/context.ts
new file mode 100644
index 000000000..b1a6ce7a2
--- /dev/null
+++ b/docs/src/lib/context.ts
@@ -0,0 +1,4 @@
+import { Context } from 'runed';
+import type { Examples } from './types';
+
+export const examples = new Context<{ readonly current: Examples }>('examples');
diff --git a/docs/src/lib/data.remote.ts b/docs/src/lib/data.remote.ts
new file mode 100644
index 000000000..56fbf9908
--- /dev/null
+++ b/docs/src/lib/data.remote.ts
@@ -0,0 +1,445 @@
+import { celsiusToFahrenheit } from 'layerchart';
+import { parse, sortFunc } from '@layerstack/utils';
+import { ascending, flatGroup, max, mean, min } from 'd3-array';
+import { csvParse, csvParseRows, autoType } from 'd3-dsv';
+
+import { prerender, getRequestEvent, query } from '$app/server';
+import { z } from 'zod';
+
+import type { PenguinsData } from '$static/data/examples/penguins.js';
+import type { AppleStockData } from '$static/data/examples/date/apple-stock.js';
+import type { USSenatorsData } from '$static/data/examples/us-senators';
+import type { CivilizationTimeline } from '$static/data/examples/date/civilization-timeline.js';
+import type { HydroData } from '$static/data/examples/date/hydro.js';
+import type { AppleTickerData } from '$static/data/examples/date/apple-ticker.js';
+import type { NewPassengerCars } from '$static/data/examples/new-passenger-cars.js';
+
+export const getGroupData = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/group-data.json').then((r) => r.json())) as {
+ x: number;
+ y: number;
+ group: string;
+ }[];
+ return data;
+});
+
+export const getAppleStock = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = await fetch('/data/examples/date/apple-stock.json').then(async (r) =>
+ parse(await r.text())
+ );
+ return data;
+});
+
+export const getAppleStockRange = query(
+ z.object({
+ start: z.string().optional(),
+ end: z.string().optional(),
+ maxPoints: z.number().optional().default(300)
+ }),
+ async ({ start, end, maxPoints }) => {
+ const { fetch } = getRequestEvent();
+ let data = await fetch('/data/examples/date/apple-stock.json').then(async (r) =>
+ parse(await r.text())
+ );
+
+ if (start || end) {
+ const startDate = start ? new Date(start) : undefined;
+ const endDate = end ? new Date(end) : undefined;
+ data = data.filter(
+ (d) => (!startDate || d.date >= startDate) && (!endDate || d.date <= endDate)
+ );
+ }
+
+ if (data.length > maxPoints) {
+ const step = (data.length - 1) / (maxPoints - 1);
+ data = Array.from({ length: maxPoints }, (_, i) => data![Math.round(i * step)]);
+ }
+
+ return data;
+ }
+);
+
+export const getDailyTemperature = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = await fetch('/data/examples/date/daily-temperature.json').then(async (r) =>
+ parse<{ date: Date; value: number }[]>(await r.text())
+ );
+ return data;
+});
+
+export const getDailyTemperatures = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = await fetch('/data/examples/dailyTemperatures.csv').then(async (r) => {
+ return csvParse<{ dayOfYear: number; year: number; value: number | 'NA' }>(
+ await r.text(),
+ // @ts-expect-error - autoType
+ autoType
+ )
+ .filter((d) => d.value !== 'NA' && d.dayOfYear <= 365 /* Ignore 366th day */)
+ .map((d) => {
+ const origDate = new Date(d.year, 0, d.dayOfYear);
+ return {
+ ...d,
+ date: new Date(Date.UTC(2000, origDate.getUTCMonth(), origDate.getUTCDate())),
+ value: d.value !== 'NA' ? celsiusToFahrenheit(d.value) : 'NA'
+ };
+ });
+ });
+ return data;
+});
+
+export const getSfoTemperatures = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = await fetch('/data/examples/sfoTemperatures.csv').then(async (r) => {
+ return flatGroup(
+ // @ts-expect-error - autoType
+ csvParse<{ date: Date; tavg: number; tmax: number; tmin: number }>(await r.text(), autoType),
+ (d) => new Date(Date.UTC(2000, d.date.getUTCMonth(), d.date.getUTCDate())) // group by day of year
+ )
+ .sort(([a], [b]) => ascending(a, b)) // sort chronologically
+ .map(([date, v]) => ({
+ date,
+ avg: mean(v, (d) => d.tavg || NaN),
+ min: mean(v, (d) => d.tmin || NaN),
+ max: mean(v, (d) => d.tmax || NaN),
+ minmin: min(v, (d) => d.tmin || NaN),
+ maxmax: max(v, (d) => d.tmax || NaN)
+ }));
+ });
+ return data;
+});
+
+export const getPenguins = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/penguins.csv').then(async (r) =>
+ csvParse(await r.text(), autoType)
+ )) as PenguinsData;
+ return data;
+});
+
+export const getFlare = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = await fetch('/data/examples/hierarchy/flare.json').then((r) => r.json());
+ return data;
+});
+
+export const getSimpleTree = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = await fetch('/data/examples/hierarchy/simple-tree.json').then((r) => r.json());
+ return data;
+});
+
+export type MetroData = {
+ Metro: string;
+ POP_1980: number;
+ LPOP_1980: number;
+ R90_10_1980: number;
+ POP_2015: number;
+ LPOP_2015: number;
+ R90_10_2015: number;
+ nyt_display: string;
+ state_display: string;
+ highlight: number;
+};
+
+export const getMetros = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = csvParse(
+ await (await fetch('/data/examples/metros.csv')).text(),
+ autoType
+ ) as unknown as MetroData[];
+ return data;
+});
+
+export const getUsSenators = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/us-senators.csv').then(async (r) =>
+ csvParse(await r.text(), autoType)
+ )) as USSenatorsData;
+ return data;
+});
+
+export const getAlphabet = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/alphabet.csv').then(async (r) =>
+ csvParse(await r.text(), autoType)
+ )) as { letter: string; frequency: number }[];
+ return data;
+});
+
+export const getOlympians = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/olympians.json').then((r) => r.json())) as {
+ name: string;
+ weight: number;
+ height: number;
+ }[];
+ return data;
+});
+
+export const getUsEvents = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = await fetch('/data/examples/date/us-events.csv').then(async (r) => {
+ return csvParse(await r.text(), autoType).map((d: any) => {
+ return {
+ startDate: new Date(d.startYear, 0, 1),
+ endDate: new Date(d.endYear, 11, 31),
+ event: d.event
+ };
+ });
+ });
+ return data;
+});
+
+export const getCivilizationEvents = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = await fetch('/data/examples/date/civilization-timeline.csv').then(async (r) => {
+ return csvParse(
+ await r.text(),
+ // @ts-expect-error - shh
+ autoType
+ ).sort(sortFunc('start'));
+ });
+
+ return data;
+});
+
+export type SvelteCount = {
+ date: Date;
+ n: number;
+ cumsum: number;
+ category: 'svelte' | 'sveltekit';
+};
+
+export const getSvelteCounts = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = await fetch('/data/examples/date/svelte-counts.csv').then(async (r) =>
+ // @ts-expect-error - autoType
+ csvParse(await r.text(), autoType)
+ );
+ return data;
+});
+
+export type SvelteMilestone = {
+ date: Date;
+ category: 'svelte' | 'sveltekit' | 'ecosystem';
+ label: string;
+ x: Date;
+ y: number;
+};
+
+export const getSvelteMilestones = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = await fetch('/data/examples/date/svelte-milestones.csv').then(async (r) =>
+ // @ts-expect-error - autoType
+ csvParse(await r.text(), autoType)
+ );
+ return data;
+});
+
+export const getAppleTicker = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = await fetch('/data/examples/date/apple-ticker.json').then(async (r) =>
+ parse(await r.text())
+ );
+ return data;
+});
+
+export const getCars = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = await fetch('/data/examples/cars.csv').then(async (r) =>
+ // @ts-expect-error - shh
+ csvParse(await r.text(), autoType)
+ );
+ return data;
+});
+
+export const getNewPassengerCars = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = await fetch('/data/examples/new-passenger-cars.csv').then(async (r) =>
+ // @ts-expect-error - shh
+ csvParse(await r.text(), autoType)
+ );
+ return data;
+});
+
+export const getHydro = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/date/hydro.json').then(async (r) =>
+ parse(await r.text())
+ )) as HydroData;
+ return data;
+});
+
+export type CountryGdpLifeExpectancy = {
+ title: string;
+ id: string;
+ continent: string;
+ x: number;
+ y: number;
+ value: number;
+};
+
+export const getCountryGdpLifeExpectancy = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/country-gdp-life-expectancy.json').then((r) =>
+ r.json()
+ )) as CountryGdpLifeExpectancy[];
+ return data;
+});
+
+export const getForceGroupDots = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/force-group-dots.json').then((r) => r.json())) as {
+ category: string;
+ value: number;
+ }[];
+ return data;
+});
+
+export const getWideData = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/bench/wide_data/data.json').then((r) => r.json())) as {
+ epoch: number;
+ idl: number;
+ recv: number;
+ send: number;
+ writ: number;
+ used: number;
+ free: number;
+ }[];
+ return data;
+});
+
+export const getDimensionArrays = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/bench/dimension_arrays/data.json').then((r) =>
+ r.json()
+ )) as {
+ date: number[];
+ cpu: number[];
+ ram: number[];
+ tcp: number[];
+ };
+ return data;
+});
+
+export const getSeriesArrays = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/bench/series_arrays/data.json').then((r) =>
+ r.json()
+ )) as {
+ cpu: {
+ x: Date;
+ y: number;
+ }[];
+ ram: {
+ x: Date;
+ y: number;
+ }[];
+ tcp: {
+ x: Date;
+ y: number;
+ }[];
+ };
+ return data;
+});
+
+export type VolcanoData = {
+ width: number;
+ height: number;
+ values: number[];
+};
+
+export const getVolcano = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/volcano.json').then((r) => r.json())) as VolcanoData;
+ return data;
+});
+
+export type WaterVaporData = {
+ width: number;
+ height: number;
+ values: number[];
+};
+
+export const getWaterVapor = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const rows = csvParseRows(
+ await fetch('/data/examples/geo/water-vapor.csv').then((r) => r.text())
+ );
+ return {
+ width: rows[0]?.length ?? 0,
+ height: rows.length,
+ values: rows.flat().map((value) => (value === '99999.0' ? NaN : +value))
+ } satisfies WaterVaporData;
+});
+
+export type FaithfulData = { eruptions: number; waiting: number };
+
+export const getFaithful = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/faithful.json').then((r) =>
+ r.json()
+ )) as FaithfulData[];
+ return data;
+});
+
+export type CategoryBrand = {
+ date: Date;
+ name: string;
+ category: string;
+ value: number;
+};
+
+export const getCategoryBrands = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/category-brands.csv').then(async (r) =>
+ csvParse(await r.text(), autoType)
+ )) as unknown as CategoryBrand[];
+
+ // Ensure dates are Date objects
+ for (const d of data) {
+ d.date = new Date(d.date as unknown as string);
+ }
+
+ return data;
+});
+
+export type ProgrammingLanguage = {
+ date: Date;
+ name: string;
+ value: number;
+};
+
+export const getProgrammingLanguages = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/programming-languages.csv').then(async (r) =>
+ csvParse(await r.text(), autoType)
+ )) as unknown as ProgrammingLanguage[];
+
+ for (const d of data) {
+ d.date = new Date(d.date as unknown as string);
+ }
+
+ return data;
+});
+
+export const getShapeData = query(z.string().nullable(), async (file) => {
+ if (!file) return null;
+ const { fetch } = getRequestEvent();
+ const geojson = await fetch(file).then((r) => r.json());
+ return geojson;
+});
+
+export type TdfStageData = { long: number; lat: number; elev: number }[];
+
+export const getTdfStage = prerender(async () => {
+ const { fetch } = getRequestEvent();
+ const data = (await fetch('/data/examples/geo/tdf-stage.json').then((r) =>
+ r.json()
+ )) as TdfStageData;
+ return data;
+});
diff --git a/docs/src/lib/examples-glob.ts b/docs/src/lib/examples-glob.ts
new file mode 100644
index 000000000..27b0a702f
--- /dev/null
+++ b/docs/src/lib/examples-glob.ts
@@ -0,0 +1,26 @@
+/**
+ * Glob-based example loaders
+ *
+ * ONLY import this module when you need to iterate over ALL examples
+ * (e.g., screenshot generation). For normal page loading, use $lib/examples.ts instead.
+ *
+ * Using import.meta.glob causes Vite to pre-transform all matched files during development.
+ */
+
+export const componentExamples = import.meta.glob('/src/examples/components/**/*.svelte', {
+ import: 'default'
+});
+
+export const componentSources = import.meta.glob('/src/examples/components/**/*.svelte', {
+ import: 'default',
+ query: '?raw'
+});
+
+export const utilExamples = import.meta.glob('/src/examples/utils/**/*.svelte', {
+ import: 'default'
+});
+
+export const utilSources = import.meta.glob('/src/examples/utils/**/*.svelte', {
+ import: 'default',
+ query: '?raw'
+});
diff --git a/docs/src/lib/examples.ts b/docs/src/lib/examples.ts
new file mode 100644
index 000000000..ba6562a13
--- /dev/null
+++ b/docs/src/lib/examples.ts
@@ -0,0 +1,104 @@
+/**
+ * Example file loaders using dynamic imports
+ *
+ * Uses dynamic imports to load examples on-demand without pre-loading
+ * all files via import.meta.glob (which causes Vite to pre-transform all matched files).
+ */
+
+import type { Component } from 'svelte';
+import type { LoadedExample } from '$lib/types.js';
+
+/**
+ * Load a single example component and its source
+ */
+export async function loadExample(
+ component: string,
+ name: string,
+ type: 'components' | 'utils' = 'components'
+): Promise {
+ try {
+ // Use dynamic imports with template literals
+ // Vite can still analyze these but won't pre-load all files
+ const [componentModule, rawSource] = await Promise.all([
+ import(`../examples/${type}/${component}/${name}.svelte`),
+ import(`../examples/${type}/${component}/${name}.svelte?raw`)
+ ]);
+
+ const { default: comp, ...module } = componentModule as {
+ default: Component;
+ title?: string;
+ description?: string;
+ layers?: string[];
+ };
+ const source = (rawSource.default as string)
+ .replace(/')
+ .trim();
+}
+
+/**
+ * Escape special markdown characters in table cells
+ */
+function escapeMarkdown(text: string): string {
+ return text.replace(/\|/g, '\\|').replace(/\n/g, ' ').replace(/